抢占正在执行同步方法的线程

时间:2011-05-25 11:16:13

标签: java thread-safety

提供以下代码

    class Test{
       double x;
       public void synchronized a()
       { 
          x = 0;
          //do some more stuff
       }
       public void b() 
       { 
          x = -1; 
       } 
    }

在修改x的中间的()中的线程是否可以被一个在同一个对象上调用b()的线程抢占?

是不是像单个原子操作一样执行同步方法?

我相信另一种方式是可能的(b()中的线程可以被调用同一对象上的()的线程抢占,因为b()没有保护我的Test对象锁。

有人可以对此有所了解吗?

2 个答案:

答案 0 :(得分:11)

synchronized仅阻止其他线程获取同一监视器。它在中没有使操作成为原子。特别是:

  • 其他未尝试在同一台显示器上同步的线程可以观察到该方法的副作用
  • 如果发生异常,则没有任何回滚
  • 其他线程可以访问和修改synchronized方法使用的相同数据(如果它们未在同一台监视器上同步)

b()未同步,因此一个线程完全可以执行a()而另一个线程可以同时执行b()

答案 1 :(得分:0)

由于b()未同步且a()已同步,因此一个帖子可能位于a()而另一个位于b()。因此,由于x的并行非同步访问,x的值很可能会出现乱码。

此外,如果您的代码是这样的:

class Test{
       double x;
       public void synchronized a()
       { 
          x = 0;
          //do some more stuff
       }
       public void b() 
       { 
          x = -1; 
          a(); //added call to a()
       } 
    }

并且您的两个线程都在相同的实例上运行,然后出现线程1 [当前在a()中被线程2抢占的可能性[目前在b() ]。

但是,在线程1被抢占后,当线程2尝试进入a()方法时,JVM将不允许它;因为另一个线程[虽然是一个非运行的线程]已经锁定它。因此,现在线程2将等待,直到线程1完成a()的执行并返回。然后线程2 [很可能]将恢复生命并允许执行a()