用Java实现互斥
我目前正在学习Java中的线程同步,并选择自己做一些测试。该程序包含几个线程,这些线程访问一个方法,将1添加到共享int,并打印哪个线程刚刚使用了该方法以及x的新值。目标是让线程从0计数到10,并按如下正确顺序打印:用Java实现互斥,java,multithreading,locking,mutex,Java,Multithreading,Locking,Mutex,我目前正在学习Java中的线程同步,并选择自己做一些测试。该程序包含几个线程,这些线程访问一个方法,将1添加到共享int,并打印哪个线程刚刚使用了该方法以及x的新值。目标是让线程从0计数到10,并按如下正确顺序打印: public int addNumbers() { x++; if (x >= 10) { running = false; } return x; } 线程: private class RunThread extends
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());
}
}
}
为了创建互斥锁,我使用了一个可重入锁,但我有一些问题:
为什么这会保证互斥并使线程以正确的顺序打印数字…:
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();
}
}
看起来它对我也有同样的影响。为什么我在方法中添加一个线程时它会突然起作用呢
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();
}
}
我试着在网上阅读,但对我来说毫无意义。
请帮助我,我只是刚刚开始学习多线程
预期“正确”结果(正常计数):
一,
二,
三,
四,
五,
六,
七,
八,
九,
十,
十一,
错误结果:
二,
三,
一,
四,
五,
七,
六,
九,
八,
十,
完整代码:
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();
}
}
}
}
在一个例子中,你有
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
一般来说,如果添加
sleep
“修复”类似的内容,则在未完全指定关系之前发生。定义“正确顺序”是什么。你期望发生什么?确切地说,为什么?到底发生了什么?在任何情况下,我的期望都是一个不确定的顺序。这是完全有道理的。非常感谢你!