gpt4 book ai didi

java - 使用锁和同步的组合会导致意外结果

转载 作者:太空宇宙 更新时间:2023-11-04 07:13:10 25 4
gpt4 key购买 nike

驱动程序.java

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Driver {

static Lock lock = new ReentrantLock();
static Integer incr = 20;

public static void main(String [] arg) throws InterruptedException
{
Thread thr1 = new Thread(new Runnable(){
@Override
public void run() {
lock.lock();
System.out.println("Gained access! - 1");
try {Thread.sleep(5000);} catch (InterruptedException e) {}
incr++;
lock.unlock();
}
});

Thread thr2 = new Thread(new Runnable(){
@Override
public void run() {
lock.lock();
System.out.println("Gained access! - 2");
incr++;
lock.unlock();
}
});

Thread thr3 = new Thread(new Runnable(){
@Override
public void run() {
synchronized(incr){
System.out.println("Gained access! - 3");
try {Thread.sleep(5000);} catch (InterruptedException e) {}
incr++;
}
}
});

Thread thr4 = new Thread(new Runnable(){
@Override
public void run() {
synchronized(incr){
System.out.println("Gained access! - 4");
incr++;
}
}
});

thr1.start();
thr2.start();
thr3.start();
thr4.start();

thr1.join();
thr2.join();
thr3.join();
thr4.join();

System.out.println(incr);
}
}

运行 1 - 输出

Gained access! - 3
Gained access! - 2
Gained access! - 1
Gained access! - 4
23

运行 2 - 输出

Gained access! - 1
Gained access! - 4
Gained access! - 3
Gained access! - 2
24

运行 N - 输出

Switching orders of Thread execution. Seen it hit a sum of 22.

问题

我正在尝试做一个简单的可重入锁和同步练习。

  1. 这些输出是否表明 ReentrantLock 在内部使用 synchronized
  2. 这些锁/同步基本上是 while 循环直到变量可访问,还是执行实际上暂停(以字节码形式)直到对象/锁解锁?
  3. 为什么在上面的例子中总和不总是 24?线程执行以下操作:

    Thread 1: Lock| 5s wait | value++
    Thread 2: Lock| 0s wait | value++
    Thread 3: syncronized | 5s wait | value++
    Thread 4: syncronized | 0s wait | value++

4。有人可以确认这基本上是 synchronized 内部所做的事情吗?我对 synchronized 的内部工作原理了解甚少。我认为这可能是复制同步的逻辑方法。所以,我再次不确定这是否是正确的方法。因此,如果 Java 的内部工作原理与此不同,请告诉我。

public class Driver {

static Safe<Integer> value = new Safe<Integer>(20);

public static void main(String [] arg) throws InterruptedException
{
Thread thr1 = new Thread(new Runnable(){
@Override
public void run() {
value.lock();
System.out.println("Gained access! - 1");
value.data++;
try {Thread.sleep(5000);} catch (InterruptedException e) {}
value.unlock();
}
});

Thread thr2 = new Thread(new Runnable(){
@Override
public void run() {
value.lock();
System.out.println("Gained access! - 2");
value.data++;
try {Thread.sleep(5000);} catch (InterruptedException e) {}
value.unlock();
}
});


thr1.start();
thr2.start();

thr1.join();
thr2.join();

System.out.println(value);
}
}

class Safe<E>{
private volatile boolean lock = false;
protected E data;

public Safe(E d)
{
data = d;
}
public String toString()
{
return data.toString();
}
public void lock()
{
while(isLocked()){}
lock = true;
}
public void unlock()
{
lock = false;
}
public boolean isLocked()
{
return lock;
}
}

谢谢!

最佳答案

  1. 他们可能会这样做,但这个结果并没有说明这一点。你为什么那么想?不管怎样,the synchronized statement uses monitorenter and monitorexit ,它使用 this (或其编码)作为条件变量,这又与您的 ReentrantLock 不同。线程总是以不同的顺序执行的原因很简单,执行顺序取决于系统调度程序。线程排队创建的顺序通常不是它们第一次运行的顺序。
  2. 如果你追踪Java框架代码,你最终会发现Unsafe.park被调用,其实现依赖于系统。这意味着,除非有人能制作一份官方的 Java 文档来说明实现策略,否则我们不知道它是否使用 "busy waiting" (循环直到锁可用),wait-notify或者两者的混合,并且它可能(并且很可能确实)在不同的系统和 Java 版本之间有所不同。
  3. 您的总和并不总是正确的,因为您存在竞争条件,因为 synchronizedlock() 针对不同的信号量进行锁定。具体来说,线程 1 和 2 彼此同步,但与 3 和 4 不同步。因为您有两个同步增量,所以您将始终看到至少两个增量(因此总和始终至少为 22)。

关于java - 使用锁和同步的组合会导致意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20340735/

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