Java synchronized 锁字符串注意点

Java Lock 大约 5075 字

描述

使用synchronized关键字,根据不同字符串进行上锁。

public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
        String lock = String.valueOf(i % 2);
        int finalI = i;
        new Thread(() -> {
            synchronized (lock) {
                System.out.println(LocalDateTime.now() + ", lock Current value#" + finalI + ", Current lock#" + lock + ", Current Thread#" + Thread.currentThread().getId());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(LocalDateTime.now() + ", unlock Current value#" + finalI + ", Current lock#" + lock + ", Current Thread#" + Thread.currentThread().getId());
            }
        }).start();
    }
}

日志输出

2020-08-21T10:14:57.410, lock Current value#1, Current lock#1, Current Thread#13
2020-08-21T10:14:57.410, lock Current value#5, Current lock#1, Current Thread#17
2020-08-21T10:14:57.410, lock Current value#2, Current lock#0, Current Thread#14
2020-08-21T10:14:57.409, lock Current value#6, Current lock#0, Current Thread#18
2020-08-21T10:14:57.409, lock Current value#0, Current lock#0, Current Thread#12
2020-08-21T10:14:57.410, lock Current value#9, Current lock#1, Current Thread#21
2020-08-21T10:14:57.409, lock Current value#4, Current lock#0, Current Thread#16
2020-08-21T10:14:57.409, lock Current value#3, Current lock#1, Current Thread#15
2020-08-21T10:14:57.410, lock Current value#8, Current lock#0, Current Thread#20
2020-08-21T10:14:57.409, lock Current value#7, Current lock#1, Current Thread#19
2020-08-21T10:15:02.410, unlock Current value#0, Current lock#0, Current Thread#12
2020-08-21T10:15:02.410, unlock Current value#4, Current lock#0, Current Thread#16
2020-08-21T10:15:02.410, unlock Current value#5, Current lock#1, Current Thread#17
2020-08-21T10:15:02.410, unlock Current value#9, Current lock#1, Current Thread#21
2020-08-21T10:15:02.410, unlock Current value#6, Current lock#0, Current Thread#18
2020-08-21T10:15:02.410, unlock Current value#2, Current lock#0, Current Thread#14
2020-08-21T10:15:02.411, unlock Current value#3, Current lock#1, Current Thread#15
2020-08-21T10:15:02.410, unlock Current value#1, Current lock#1, Current Thread#13
2020-08-21T10:15:02.411, unlock Current value#7, Current lock#1, Current Thread#19
2020-08-21T10:15:02.411, unlock Current value#8, Current lock#0, Current Thread#20

原因

使用字符串锁,但每次都是new了一个新对象,所以起不了锁的效果。而如果测试synchronized ("1")锁固定常量字符串则锁有效。

原因是:new的对象在堆上分配,每次都不同。

解决方法

使用Stringintern()方法,将堆上的String写入常量池中。常量池中如果有数据,则直接取常量池中数据;常量池中如果没有数据,则将数据写入常量池并返回常量池中的数据。

public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
        String lock = String.valueOf(i % 2);
        int finalI = i;
        new Thread(() -> {
            synchronized (lock.intern()) {
                System.out.println(LocalDateTime.now() + ", lock Current value#" + finalI + ", Current lock#" + lock + ", Current Thread#" + Thread.currentThread().getId());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(LocalDateTime.now() + ", unlock Current value#" + finalI + ", Current lock#" + lock + ", Current Thread#" + Thread.currentThread().getId());
            }
        }).start();
    }
}

日志输出

2020-08-21T10:14:00.774, lock Current value#1, Current lock#1, Current Thread#13
2020-08-21T10:14:00.774, lock Current value#0, Current lock#0, Current Thread#12
2020-08-21T10:14:05.775, unlock Current value#1, Current lock#1, Current Thread#13
2020-08-21T10:14:05.775, unlock Current value#0, Current lock#0, Current Thread#12
2020-08-21T10:14:05.775, lock Current value#5, Current lock#1, Current Thread#17
2020-08-21T10:14:05.775, lock Current value#8, Current lock#0, Current Thread#20
2020-08-21T10:14:10.776, unlock Current value#5, Current lock#1, Current Thread#17
2020-08-21T10:14:10.776, unlock Current value#8, Current lock#0, Current Thread#20
2020-08-21T10:14:10.776, lock Current value#9, Current lock#1, Current Thread#21
2020-08-21T10:14:10.776, lock Current value#4, Current lock#0, Current Thread#16
2020-08-21T10:14:15.776, unlock Current value#9, Current lock#1, Current Thread#21
2020-08-21T10:14:15.776, unlock Current value#4, Current lock#0, Current Thread#16
2020-08-21T10:14:15.776, lock Current value#7, Current lock#1, Current Thread#19
2020-08-21T10:14:15.776, lock Current value#6, Current lock#0, Current Thread#18
2020-08-21T10:14:20.777, unlock Current value#6, Current lock#0, Current Thread#18
2020-08-21T10:14:20.777, unlock Current value#7, Current lock#1, Current Thread#19
2020-08-21T10:14:20.777, lock Current value#2, Current lock#0, Current Thread#14
2020-08-21T10:14:20.777, lock Current value#3, Current lock#1, Current Thread#15
2020-08-21T10:14:25.778, unlock Current value#2, Current lock#0, Current Thread#14
2020-08-21T10:14:25.778, unlock Current value#3, Current lock#1, Current Thread#15
阅读 751 · 发布于 2020-09-24

————        END        ————

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
随便看看 换一批