Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我可以使用静态布尔变量作为同步线程的锁吗?_Java_Multithreading_Synchronized - Fatal编程技术网

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
    }
}

很抱歉,这提供了负值,因为它没有任何保证,只会给人一种安全的错觉。这有几个问题:

  • 该变量是非易失性的,因为一个线程的此类更改可能对另一个线程不可见
  • 您的锁定不是原子的。因此,两个线程都可以通过while循环,然后都将布尔值设置为true
  • notifyAll()
    唤醒等待对象实例的所有线程。由于每个线程都在等待自己作为监视器,因此它们不会被唤醒 Java中有很多很好的锁定机制——试试并发包中的那些(尽管在您的例子中,一个简单的同步块就足够了)。如果坚持使用布尔值作为锁,则需要:

  • 当你发信号时做一个静态的final
    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);
                }
            }
        }
    }