Java 我可以使用静态布尔变量作为同步线程的锁吗?
我尝试使用静态布尔变量来锁定和解锁两个同步线程。 因此,我编写了以下代码:Java 我可以使用静态布尔变量作为同步线程的锁吗?,java,multithreading,synchronized,Java,Multithreading,Synchronized,我尝试使用静态布尔变量来锁定和解锁两个同步线程。 因此,我编写了以下代码: public class Main { public static void main(String[] args){ //MyObject lock = new MyObject(); Thread1 t1 = new Thread1(100,'#'); Thread1 t2 = new Thread1(100,'*'); t1.start(
public class Main {
public static void main(String[] args){
//MyObject lock = new MyObject();
Thread1 t1 = new Thread1(100,'#');
Thread1 t2 = new Thread1(100,'*');
t1.start();
t2.start();
}
}
为什么它不起作用
notify()
和wait()
使用调用它们的对象的“监视器”。在您的例子中,这就是正在运行的this
,即Thread1
的特定实例
因此,当Thread-0
运行时:
- 它检查
锁
- 找到它
false
- 它运行主代码
- 它调用
上的this
(它本身就是notifyAll()
)Thread-0
Thread-1
运行:
- 它检查
锁
- 发现它是
true
- 并调用
上的this
(它本身就是wait()
)Thread-1
Thread-0
在this
(本身)上调用notifyAll()
,而Thread-1
在this
(本身)上调用wait()
,Thread-1
在不同的监视器上等待,因此它永远不会被释放
解决方案
如果您的计划只是让代码按顺序运行,请使用以下方法:
public class Thread1 extends Thread {
private static final Object lock = new Object();
public void run(){
// non-sequential code
System.out.println(getName() + " is running");
synchronized (lock) {
// this code will be run sequentially by one thread at a time
}
// non-sequential code
}
}
很抱歉,这提供了负值,因为它没有任何保证,只会给人一种安全的错觉。这有几个问题:
notifyAll()
唤醒等待对象实例的所有线程。由于每个线程都在等待自己作为监视器,因此它们不会被唤醒李>
Java中有很多很好的锁定机制——试试并发包中的那些(尽管在您的例子中,一个简单的同步块就足够了)。如果坚持使用布尔值作为锁,则需要:
AtomicBoolean
(非final是可以的,只要你不改变它并保证可见性)compareAndSet
作为循环/锁定条件,以便访问是原子的AtomicBoolean
上的Wait()
,以便线程共享它们正在等待的监视器(以及它上的notifyAll()
)可以使用更简单的方法同步线程
class Thread1 extends Thread {
private static final Object lock = new Object();
int myNum;
char myChar;
public Thread1(int num, char c){
myNum = num;
myChar = c;
}
public void run(){
System.out.println(getName() + " is runing");
synchronized(lock) {
for(int i = 0; i<myNum; i++){
if(i%10==0)
System.out.println("");
System.out.print(myChar);
}
}
}
}
class Thread1扩展了线程{
私有静态最终对象锁=新对象();
int myNum;
char-myChar;
公共线程1(int num,char c){
myNum=num;
myChar=c;
}
公开募捐{
System.out.println(getName()+“正在运行”);
已同步(锁定){
对于(int i=0;如果你想串行运行线程,我也可以使用循环而不是线程。学习多线程的经典示例是实现生产者/消费者线程。生产者生产东西并通知消费者;同时消费者在消费东西后等待。呃,Jamie不是已经提供了一段几乎相同的代码吗h一些解释(在我的回答中也简要提到)?此外,您不需要锁上的notifyAll。您可以进一步解释问题3吗?如果线程正在等待自己作为监视器,为什么它不会被唤醒?线程等待对象实例。在这种情况下,您有两个实例:t1
和t2
。线程1等待t1
。线程2工作,完成后通知等待通知的对象上的所有东西都被调用,即t2
。但是,没有任何东西在等待t2
(t1
和t2
是不同的对象),因此没有任何东西被唤醒。为什么“公共静态最终对象锁定”需要是最终的吗?@YuvalLevy不需要,但它告诉我们线程无法更改它。如果发生这种情况,那么等待旧实例的对象将不会通过调用新对象得到通知。@YuvalLevy还应该是私有的,因为它在Thread1
类之外没有任何用处。(已编辑)
public class Thread1 extends Thread {
private static final Object lock = new Object();
public void run(){
// non-sequential code
System.out.println(getName() + " is running");
synchronized (lock) {
// this code will be run sequentially by one thread at a time
}
// non-sequential code
}
}
class Thread1 extends Thread {
private static final Object lock = new Object();
int myNum;
char myChar;
public Thread1(int num, char c){
myNum = num;
myChar = c;
}
public void run(){
System.out.println(getName() + " is runing");
synchronized(lock) {
for(int i = 0; i<myNum; i++){
if(i%10==0)
System.out.println("");
System.out.print(myChar);
}
}
}
}