在尝试进入条件之前,我试图了解锁和多线程的工作方式。这是我当前正在测试的代码:
public class tester {
private static int count = 0;
public void incrementCount() {
count++;
}
public int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new testing());
Thread thread2 = new Thread(new testing());
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
}
这是实现Runnable的部分:
public class testing implements Runnable {
Lock lock = new ReentrantLock();
tester in = new tester();
public void run() {
for (int i = 0; i < 1000; i++) {
lock.lock();
in.incrementCount();
lock.unlock();
}
}
}
我遇到的问题是我试图在main方法的末尾打印出2000,但是即使使用锁,它也从未真正输出到2000。帮助将不胜感激!
答案 0 :(得分:2)
即使我正在使用锁。
您正在为两个线程中的每个线程使用单独的锁。
如果您希望锁在线程之间进行协调,则它们都需要使用相同的锁实例。否则就没有意义了。
更改为类似
class Testing implements Runnable {
private final Lock lock;
// pass in the lock to use via the constructor
// both threads need to receive the same lock
Testing(Lock lock){ this.lock = lock; }
public void run() {
for (int i = 0; i < 1000; i++) {
lock.lock();
Tester.incrementCount();
lock.unlock();
}
}
}
答案 1 :(得分:1)
锡洛是正确的,但我认为可以用另一种方式解释它。
锁(Lock
实现和原始锁)的主要目的是获得对某些数据的互斥访问。 “协议”为:
假设是,当一个线程持有该锁时,没有其他线程可以访问数据 1 。
但这仅在锁和数据之间存在一对一关联时才有效。也就是说,您需要获取数据的锁 才能获得独占访问权限。如果您获得了另一组数据的锁,它将无法正常工作。如果您尝试对同一组数据使用多个锁,通常 2 也将不起作用。
在您的示例中,每个线程都有自己的锁,但是只有一个数据正在尝试控制对它们的访问。结果,两个线程可以同时访问和更新数据。
Thilo的答案显示了(一种)解决问题的正确方法。
1-这实际上是线程之间的“契约”。 Java语言不会(也不能)阻止线程在不持有锁的情况下访问和更新“受控”数据。线程必须遵守合同才能实现正确的同步和互斥。
2-通常但并非总是如此。例如,ReadWriteLock
提供了一对锁对象,它们一起提供互斥的读写访问权限或共享的只读访问权限。