java - 创建和使用 String 对象来锁定线程同步是一个好习惯吗?

标签 java string multithreading synchronization synchronized

对不起我的英语

我不使用任何字段进行锁定,因为所以我不应该考虑某些字段是否可以具有值 null

我总是创建仅用于线程同步锁定的特殊字段。

例如:

public class Worker {

    private static final List<Toilet> TOILETS = Arrays.asList(
        new Toilet(1),
        new Toilet(2),
        // ...
        new Toilet(NUMBER_OF_FLOORS)
    );

    // here it is:
    private static final List<String> LOCK_TOILETS = Arrays.asList(
        "LOCK TOILET #1",
        "LOCK TOILET #2",
        // ...
        "LOCK TOILET #" + NUMBER_OF_FLOORS
    );

    private final int floorNumber;

    public void spendWorkingHours() {
        for (int i = 0; i < X; ++i) {
            doWork();
            snackSomething();
            String lockToilet = LOCK_TOILETS.get(floorNumber);
            Toilet theOnlyToiletOnTheFloor = TOILETS.get(floorNumber);
            synchronized (lockToilet) {
                goToToilet(theOnlyToiletOnTheFloor);
            }
        }

    }

}

最佳答案

您不应该使用String来锁定对象,尤其是字符串文字

字符串文字来自于String池,并且相同字符串的每个String文字都是相同引用。这意味着如果两个不同的线程使用两个“不同”的字符串文字实际上是相同的,因此很容易发生死锁。

演示:

// Thread #1
String LOCK1 = "mylock";
synchronized (LOCK1) {
}

// Thread #2
String LOCK2 = "mylock";
synchronized (LOCK2) {
    // This is actually the SAME lock,
    // might cause deadlock between the 2 synchronized blocks!
    // Because LOCK1==LOCK2!
}

最好是同步无法从“外部”访问的私有(private)对象。如果您使用从“外部”可见(或由方法返回)的 Object 锁,则任何人都可以将该对象用作您无法控制的锁,并且可能会导致与您的内部synchronized block 发生死锁。
例如,您可以同步想要保护的对象(如果它是私有(private)的),或者创建一个私有(private)的内部锁Object:

private final Object LOCK = new Object();

// Later:
synchronized (LOCK) {
    // LOCK is not known to any "outsiders", safe to use it as internal lock
}

关于java - 创建和使用 String 对象来锁定线程同步是一个好习惯吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25863255/

相关文章:

java - 如何使用对象名称字段按字母顺序对 List<Object> 进行排序

c# - WP7(C#)的简单LOCK和ThreadPoolQuestion

java - 池化数据库连接没有立即使用的情况叫什么?

c - 在 C 中定义长度前缀 const 宽字符串

java - Java 中的 List<String> 错误

c++ - 为什么关系运算符在 STL 字符串中重载为非成员函数?

C# - 遍历从新线程传递的对象参数

c++ - 如果atomic_compare_exchange在它自己的线程上不是原子的,它如何实现锁?

java - Android布局-如何在矩形上画一个洞

java - 为什么我的日期没有被正确设置为 future 30 天?