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

Java 抢占正在执行同步方法的线程,java,thread-safety,Java,Thread Safety,给出以下代码 class Test{ double x; public void synchronized a() { x = 0; //do some more stuff } public void b() { x = -1; } } 在修改X的过程中,(a)中的线程是否可以通过在同一对象上调用B()的线程抢

给出以下代码

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

在修改X的过程中,(a)中的线程是否可以通过在同一对象上调用B()的线程抢占? 同步方法不是像执行单个原子操作一样执行吗

我相信另一种方法是可能的(b()中的线程可以被调用同一对象上的a()的线程抢占,因为b()没有受到测试对象锁的保护)


有人能解释一下吗?

synchronized
只会阻止其他线程获取相同的监视器。它决不会使操作原子化。特别是:

  • 该方法的副作用可由不尝试在同一监视器上同步的其他线程观察到
  • 如果发生异常,则不会进行回滚
  • 其他线程可以访问和修改synchronized方法使用的相同数据,如果它们没有在同一监视器上同步
b()
是不同步的,因此一个线程完全可能同时执行
a()
和另一个线程同时执行
b()

因为
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()

另一个与此无关的问题源问题是,如果同步方法需要太多时间来执行,操作系统调度程序是否可以抢占它并切换到另一个线程?如果可能,此线程是否会释放锁?@Richard:不,这不会释放锁。同步方法可以占用它想要的时间,并且是emp之前的ted多次-当同步方法拥有锁时,任何东西都无法获取该锁。(请注意,调用
wait()
会释放锁,但稍后会重新获取它。)