【问题标题】:Mutex implementation in JavaJava中的互斥锁实现
【发布时间】:2018-08-12 14:50:12
【问题描述】:

我目前正在学习 Java 中的线程同步,并选择自己做一些测试。该程序包含几个线程,它们访问一个方法以将 1 添加到共享 int 并打印哪个线程刚刚使用了该方法以及 x 的新值是什么。目标是让线程从 0 增加到 10 并以正确的顺序打印,如下所示:

public int addNumbers() {
    x++;
    if (x >= 10) {
        running = false;
    }
    return x;
}

线程:

private class RunThread extends Thread {
    public void run() {
        while (running) {
            System.out.println(addNumbers());
        }
    }
}

为了创建 Mutex,我使用了 ReentrantLock,但我有一些问题:

为什么这样保证互斥并使线程以正确的顺序打印数字...:

lock.lock();
System.out.println(addNumbers());
lock.unlock();

...虽然这不是?:

public int addNumbers() {
    lock.lock();
    try {
        x++;
        if (x >= 10) {
            running = false;
        }
        return x;
    } finally {
        lock.unlock();
    }
}

看起来它对我做了同样的事情。以及为什么我在方法中添加一个 Thread.sleep 时它突然起作用了?:

public int addNumbers() {
    lock.lock();
    try {
        x++;
        if (x >= 10) {
            running = false;
        }
        return x;
    } finally {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        lock.unlock();
    }
}

我试图在网上阅读它,但它对我来说没有任何意义。 请帮助和善意,我才刚刚开始学习多线程。

预期的“正确”结果(正常计数):

1

2

3

4

5

6

7

8

9

10

11

错误的结果:

2

3

1

4

5

7

6

9

8

10

完整代码:

public class LockTest {
    int x = 0;
    boolean running = true;
    private final Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        LockTest t1 = new LockTest();
    }

    public LockTest() {
        init();
    }

    public int addNumbers() {
        x++;
        if (x >= 10) {
            running = false;
        }
        return x;
    }

    private void init() {
        Thread t1 = new RunThread();
        Thread t2 = new RunThread();
        Thread t3 = new RunThread();
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }

    private class RunThread extends Thread {
        public void run() {
            while (running) {
                lock.lock();
                System.out.println(this.getName() + ": " + addNumbers());
                lock.unlock();
            }
        }
    }
}

【问题讨论】:

  • 作为一般规则,如果添加sleep“修复”这样的事情,那么您的发生之前的关系没有完全指定。
  • 定义什么是“正确的顺序”。你预计会发生什么,为什么?相反,究竟会发生什么?在所有情况下,我的期望都是未定的订单。

标签: java multithreading locking mutex


【解决方案1】:

在一种情况下,你有

lock.lock();
System.out.println(this.getName() + ": " + addNumbers());
lock.unlock();

因此,所有线程都希望同时执行这些行,但一次只能执行一个。所以第一个线程获得锁,从而阻止其他线程获得它,然后递增并打印值,然后释放锁。然后另一个线程可以获得锁,递增和打印,然后释放锁。因此,您将获得按升序打印的值。

在第二种情况下,你只有

 System.out.println(this.getName() + ": " + addNumbers());

所以,所有线程都可以同时执行。但是,在 addNumbers 中,线程必须获得一个锁才能增加数字。因此数字以正确的顺序递增,但由于打印不在互斥锁内,因此您无法保证顺序。示例:

 - Thread 1: acquire the lock
 - Thread 1: increment x (x = 1)
 - Thread 1: read the value returned by addNumbers (= 1) to print it
 - Thread 1: release the lock
 - Thread 2: acquire the lock
 - Thread 2: increment x (x = 2)
 - Thread 2: read the value returned by addNumbers (= 2) to print it
 - Thread 2: release the lock
 - Thread 2: print the read value: 2
 - Thread 1: print the read value: 1

【讨论】:

  • 这很有意义。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 2011-07-20
  • 1970-01-01
  • 2010-12-01
  • 2011-06-23
  • 2014-12-31
  • 2012-10-27
  • 2018-05-23
相关资源
最近更新 更多