关于Java同步块的3个快速问题

Jam*_*sev 3 java synchronized

据我所知,下面的代码,在synchronized块中,this是一个计数器的实例.

问题1:在下面的示例中,这是否意味着当线程A到达synchronized块时,线程B被阻止对计数器的实例做任何事情?换句话说,这是否意味着线程可以继续按照他们的意愿执行,但是当到达 synchronized块时,另一个停止对类执行任何操作,直到块退出?

public class Counter {

    public void increment() {
        // Some code

        synchronized (this) {  // <---- "this" is an instance of Counter
             // Some more code
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

比较上面的代码

public class Counter {

    List<String> listOfStrings = new ArrayList<String>();

    public void increment() {
        // Some code

        synchronized (listOfStrings) {  
             // Some code that deals with 
             //    listOfStrings 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题2:在上面的例子中,一旦线程A到达synchronized块,线程B可以继续读出和写入任何东西的类除外listOfStringsArrayList中,这是一个mutexsynchronized块.它是否正确?

问题3:难道是进一步正确的假设,如果我们需要修改多个对象,thismutex我们应该使用?

例如:

public class Counter {

    List<String> listOfStrings = new ArrayList<String>();
    List<Integers> listOfIntegers = new ArrayList<Integers>();

    public void increment() {
        // Some code

        synchronized (this) {  
             // Some code that deals with 
             //    listOfStrings and listOfIntegers
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我理解正确吗?如果我错误的话,请更正.

Tom*_*icz 5

线程B被禁止对计数器的实例做任何事情?

不,线程B被阻止进入同步的代码块,它仍然可以输入其他方法:那些未同步的方法和使用不同对象同步的方法.线程B不仅可以访问使用已由不同线程占用的对象同步的块(同步锁是可重入的).

线程B可以继续读取和写入类中的任何内容,但不包括 listOfStrings

实际上,listOfStrings在一个synchronized块中用作互斥锁的事实并不意味着其他线程无法显式访问该对象.它只表示其他线程无法访问由同一对象保护的同步块.因此,如果要保护对listOfStrings对象的访问,则必须同步访问该对象的所有方法并使用相同的锁(例如listOfStrings).

BTW您同步的每个对象应该是final为了避免头痛.

假设我们需要对多个对象进行修改,这是我们应该使用的互斥体吗?

是的,不是.考虑以下情况:

List<String> listOfStrings = new ArrayList<String>();
List<Integers> listOfIntegers = new ArrayList<Integers>();
Set<String> setOfStrings = new HashSet<String>();
Set<Integers> setOfIntegers = new HashSet<Integers>();
Run Code Online (Sandbox Code Playgroud)

如果一个方法只访问列表而第二个方法只访问集合,则可以安全地使用两个锁 - 一个用于第一个方法,第二个用于第二个方法.同步this不会受到影响,但会影响性能:

private final Object listLock = new Object();
private final Object setLock = new Object();
Run Code Online (Sandbox Code Playgroud)

然后:

synchronized (listLock) {  
     // Some code that deals with 
     // setOfStrings and setOfIntegers
}

//...

synchronized (setLock) {  
     // Some code that deals with 
     // setOfStrings and setOfIntegers
}
Run Code Online (Sandbox Code Playgroud)