gpt4 book ai didi

java - synchronized (this) 是只锁定同步块(synchronized block)还是锁定所有 "this"代码?

转载 作者:搜寻专家 更新时间:2023-11-01 01:42:05 29 4
gpt4 key购买 nike

public class ObjectCounter {
private static long numOfInstances = 0;
public ObjectCounter(){
synchronized(this){
numOfInstances++;
}
}
**public static synchronized long getCount(){
return numOfInstances;
}**
//vs//
**public static long getCount(){
return numOfInstances;
}**
}

如果我将运行几个线程,其中一些会调用静态函数 getCount(),而其中一些会创建新实例。我想在每次调用 getCount() 时获取当时的实际实例数。

  1. 代码中的两个选项有区别吗?
  2. 如果我锁定“this”,这是否意味着我不能调用 getCount() 直到构造函数退出同步块(synchronized block)(假设我不'在 getCount() 上写入同步。
  3. 如果我在代码的某个地方执行同步块(synchronized block),它是只锁定同步块(synchronized block)还是锁定所有“this”代码?
  4. 从这里开始 编辑:谢谢大家,这很有帮助,但在您的回答之后我还有几个问题。
  5. 如果我理解正确,synchronized(this) block 不会影响(或连接到)静态同步函数(锁定术语不是 numOfInstances 增量)?
  6. 是否有更好的选择使增量和 getCount() 函数线程安全? (比如打开一个静态对象并执行 synchronized(obj) 而不是 synchronized(this) - friend 建议)。
  7. 如果我在 ObjectCounter 类中有一个 f1() 方法(非静态),而一个线程在同步(this)中,其他线程是否可以进入 f1() block (不是同步类或内部有同步块(synchronized block))?
  8. 如果我在 ObjectCounter 中有 f1() 方法(非静态)和 f2() 方法(非静态),在 f1() 中我有 synchronized(this) block 。当一个线程在 synchronized(this) block 中时,其他线程是否可以进入 f1() block (不是同步类或内部有同步块(synchronized block))? (假设两个线程在同一个实例上“工作”)

`

最佳答案

使用synchronized 意味着为了让线程执行该 block 或方法,它必须获得该 block 或方法(显式或隐式)引用的锁。对于 static synchronized 方法,该锁是类对象上的监视器。对于 synchronized(this) block ,使用的锁是当前实例上的监视器。在多个方法或 block 之间共享锁是强制更新的原子性和内存可见性的原因,共享锁还提供了一个共享的通信路径,通过该路径可以进行等待和通知。

由于静态同步块(synchronized block)使用的锁与构造函数中的 block 使用的锁不同,因此进入静态同步块(synchronized block)不会被另一个线程访问需要获取当前实例锁的 block 阻塞,并且同步块(synchronized block)在构造函数中对任何东西都没有影响,锁获取将始终是无竞争的。在这里更重要的是,一个线程在构造函数中所做的更改可能不会被使用 getter 的其他线程看到。同步会影响锁定和内存可见性。

这个改变后的版本可以工作:

public class ObjectCounter {
private static long numOfInstances = 0;
public ObjectCounter(){
synchronized(ObjectCounter.class){
numOfInstances++;
}
}
public static synchronized long getCount(){
return numOfInstances;
}
}

因为 getter 和 incrementing block 使用的是同一个锁。让不同的线程获取相同的监视器可确保安全地发布对计数器的更改,以便访问 getter 的另一个线程可以看到更新后的值。

synchronized 关键字说,“你必须在进入之前获取一个锁”,其中对于方法锁是假定的:在方法上使用 static 关键字它是类上的监视器,没有 static 关键字它是监控当前实例。为了使锁定正常工作,不同的 block 和方法需要使用相同的锁。可以说,在 Java 的设计方式中有太多的语法糖和太多的便利:允许隐式选择锁并将监视器放在 java.lang.Object 上会导致混淆。

关于您的问题 #6:对于您在这里所做的事情,您最好使用 AtomicLong .使用同步块(synchronized block)来协调需要在不受其他线程干扰的情况下发生的多个更改。

问题#3、#7 和#8 看起来非常相似:如果方法/ block 不尝试获取锁,则没有什么可以阻止线程执行该方法/ block 。对象作为一个整体没有得到任何保护,使用同步方法或 block 来强制锁定才是保护。少考虑“使用 synchronized 关键字”,多考虑线程需要获取什么锁。

关于java - synchronized (this) 是只锁定同步块(synchronized block)还是锁定所有 "this"代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31342513/

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