gpt4 book ai didi

java - 多线程中的锁应该始终保持不可变吗?

转载 作者:行者123 更新时间:2023-12-02 01:43:02 25 4
gpt4 key购买 nike

我正在尝试下面的代码片段,它给出了预期的输出。但我很好奇我正在创建多少个锁定对象 1 或 2?

package com.practice;

class A{
String lock="";

A(String lock){
this.lock = lock;
}

A(){ }

public void printMe(int x) {
int counter = x;
synchronized (lock) {
System.out.println(++counter);
}
}
}



public class MultiThreadingPractice {

public static void main(String[] args) {
A a = new A("1");

Thread t1=new Thread(() -> {
a.printMe(1);
});

a.lock = new String();

Thread t2=new Thread(() -> {
a.printMe(1);
});

t1.start();
t2.start();
}
}

最佳答案

多线程中的锁应该始终保持不可变吗?是的。

您正在使用字符串(任何对象都可以)作为锁。当您为锁分配一个新值(新字符串)时,这意味着您有多个锁实例。只要所有线程在同一个锁实例上同步就可以了,但是 A 类 代码中没有任何明显的内容来确保情况确实如此。

在您的实际使用示例中,您是安全的。由于只有在完成对第三个也是最后一个实例的锁定之后才会启动任何线程,因此在锁定稳定之前不会尝试同步锁定。 (3 个实例:第一个是对空字符串的初始化;第二个是对提供的构造函数参数“1”的初始化;第三个是对另一个空字符串的显式赋值)。因此,虽然这段代码“有效”,但它只能通过我所说的“巧合”起作用,即它在设计上不是线程安全的。

但是让我们假设一种情况,您在构造每个线程后立即启动它。这意味着您将在 t1 运行之后但在 t2 创建之前重新分配锁定成员。

一段时间后,两个线程将在新的锁实例上同步,但在您切换锁的时间点附近的一段时间内,线程 t1 可能并且很可能处于 synchronized(lock) { .. . } 子句使用旧的锁实例。大约在那时,线程 t2 可以执行并尝试在新的锁实例上进行同步。

简而言之,您已经在打算用来消除计时窗口的机制中创建了一个计时窗口(竞争风险)。

您可以安排更高级别的同步,以允许您更换锁,但我无法想象任何直接的情况是必要的、有用的或明智的。最好在发生任何争用之前分配一个锁,然后坚持使用该锁。

附注“我要创建多少把锁?” 3.虽然前两个从未使用过。

关于java - 多线程中的锁应该始终保持不可变吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54170952/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com