Java同步块

Java同步块,java,multithreading,synchronization,Java,Multithreading,Synchronization,如果我们有一个方法: public void doSomething(){ synchronized(this){ //some code processing here } String temp = "init"; //instead of i++ synchronized(this){ //some other code processing here } } 此方法是否等同于公共同步的void doSomethin

如果我们有一个方法:

public void doSomething(){
    synchronized(this){
        //some code processing here
    }
    String temp = "init"; //instead of i++
    synchronized(this){
        //some other code processing here
    }
}
此方法是否等同于公共同步的void doSomething()

是否有任何理由认为线程调度程序在某些执行中会产生与同步整个函数相同的有效流?即:

  • Thread1进入第一个同步块
  • 螺纹2块
  • Thread1继续执行
    i++
    ,并移动到第二个同步块,而Thread2保持阻塞状态
  • 因此,Thread2在Thread1退出两个同步块后进入该方法
我只需要知道:

  • 我是否可以依赖于两个线程(Thread1和Thread2)可以同时在方法中的所有执行上下文?例如,第一个同步块中的Thread2和第二个同步块中的Thread1可以实现并发
  • 是否会有一些执行流,其中方法中(一次)只有一个线程,从而有效地序列化整个流,使其等效于
    public synchronized void doSomething()

此方法与使其成为同步方法不同。 您解释的行为可能会被看到,但永远无法得到保证。

在某些执行中,它将具有与同步整个函数相同的流,当然-但要真正等同于使方法同步,它必须具有与所有执行相同的流

实际上,在执行的中途,另一个线程可能会抓住锁(无论是对于这个方法还是同一个监视器上的其他代码锁定)。如果方法本身是同步的,就不会发生这种情况,因此它们不是等价的

(顺便说一句,锁定
这个
通常被认为是不好的做法;我不记得上次我写了一个同步的方法。我锁定了私有监视器,因此我知道我的代码是唯一可能锁定它们的代码。)

编辑:要响应您的编辑:


我只需要知道我是否能 依赖于所有执行上下文 两个螺纹(例如螺纹1和 Thread2)可以在 同一时间,例如第一个螺纹中的螺纹2 同步块和第二个线程中的线程1 同步块以实现并发

绝对不是!可以保证在同一个监视器上同步的同步块中不会同时有两个线程

代码有三部分:第一个同步块、未同步部分和第二个同步部分

一次可以在非同步部分执行任意数量的线程。对于任何一个实例(因为您正在
上同步此
),只有一个线程可以执行任何一个同步块。如果要实现并发性,必须在不同的监视器上进行同步


此外,听起来您希望确保调度器在等待锁时允许另一个线程获取锁。我不相信有任何这样的保证——执行第一个块的线程可以释放锁,但在相同的时间片中继续,并在其他线程进入之前重新获取锁。在某些JVM中,这可能不会发生,但我不相信有任何保证。

不,不会。例如上面的代码

线程1进入第一个sync'd块执行它,然后退出,然后被关闭。 线程2进入第一个sync'd块执行它,然后在被关闭之前进入第二个sync'd块。 线程1现在无法继续,直到线程2退出第二个同步块


如果整个方法是同步的,则此模式不会发生

不,它不等同于
synchronized void doSomething()
,因为
i++
不是原子操作。事实上,它可能有类似的功能

int-temp=i;i=i+1;结果=温度


如果这些操作不是原子化的,那么
i
的值可以在其处于错误状态时读取。

如果使用synchronized关键字在Java中实现监控器,则无法保证给定的代码段是同步的

实际上,两个线程是否都可能完成第一个同步块,然后在执行下一个块之前执行语句以增加
i
的值

我假设变量
I
包含两个线程之间共享的状态,在这种情况下,操作不是线程安全的。为了使操作序列线程安全,您必须确保整个序列一次由一个线程执行。在单独的监视器中执行单个操作与在没有监视器的情况下执行操作一样好;监视器必须保护整个序列

更多信息请访问artima.com,网址为

编辑

考虑到问题现在反映了本地字符串对象的使用,可以认为操作序列是线程安全的。每个线程在堆栈上创建自己对字符串对象的本地引用;由于字符串对象的不可变属性,一个线程中对象的任何变化都不会影响另一个线程(当发生变化时,会为所有实际目的创建一个新的字符串对象,因此状态不会在线程之间真正共享)

强调

在尝试线程同步时,如果对共享数据的访问是互斥的,则认为操作序列是线程安全的;这样一来,一个线程将无法读取或写入共享变量,而另一个线程正在执行涉及共享数据的操作。仅使用局部变量会消除线程之间共享的任何感觉


我需要知道的是我是否能指望所有的执行合作