我可以使用静态布尔变量作为同步线程的锁吗?

时间:2014-07-01 10:33:52

标签: 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();
        t2.start();
    }
}

public class Thread1 extends Thread {

    public static boolean lock;
    int myNum;
    char myChar;

    public Thread1(int num, char c){
        myNum = num;
        myChar = c;
        lock = false;
    }

    public synchronized void run(){
        System.out.println(getName() + " is runing");
        while (Thread1.lock == true){
            System.out.println(getName() + " is waiting");
            try{wait();}
            catch(InterruptedException e){}
        }
        Thread1.lock = true;
        for(int i = 0; i<myNum; i++){
            if(i%10==0)
                System.out.println("");
            System.out.print(myChar);
        }
        Thread1.lock = false;
        notifyAll();
    }
}

可能我做得不对,因为只有一个线程正在打印&#34; mychar&#34;而另一个线程只是进入wait()而不是在我执行notifyAll()时唤醒。 我认为这可以是为整个类使用静态布尔变量的好方法,而不是每次更改它并调用notifyAll()来检查其他对象中的这个标志......

输出示例:

Thread-0 is runing

Thread-1 is runing
Thread-1 is waiting
##########
##########
##########
##########
##########
##########
##########
##########
##########
##########

3 个答案:

答案 0 :(得分:4)

为什么它不起作用

notify()wait()使用&#34;监视器&#34;它们被调用的对象在您的情况下,这是this,即正在运行的Thread1的特定实例。

所以,当Thread-0运行时:

  • 检查lock
  • 找到它false
  • 它运行主代码
  • 它在notifyAll()上调用this(本身就是Thread-0)。

Thread-1运行:

  • 检查lock
  • 发现它是true
  • 并在wait()上调用this(本身就是Thread-1

由于Thread-0notifyAll()(本身)上调用thisThread-1wait()调用this(这是本身),Thread-1正在等待Thread-0正在通知的其他监视器上,因此它永远不会被释放。

<强>解决方案

如果您的计划是让代码按顺序运行,请使用:

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

答案 1 :(得分:1)

很抱歉,但这会带来负值,因为它没有任何保证,只会给人一种安全感。这有几个问题:

  1. 该变量是非易失性的,因为来自一个线程的更改可能对另一个线程不可见。
  2. 你的锁定不是原子的。因此,可能发生的是两个线程都可以传递while循环,然后将boolean设置为true。
  3. notifyAll()唤醒在对象实例上等待的所有线程。由于每个线程都在等待自己作为监视器,因此它们不会被唤醒。
  4. Java中有很多好的锁定机制 - 尝试并发包中的那些(虽然在你的情况下,一个简单的同步块就足够了)。如果你坚持使用布尔值来锁定,你需要:

    1. 制作一个静态的最终 AtomicBoolean作为你的信号(只要你不改变它并保证可见性,非最终会很好)
    2. 使用compareAndSet作为循环/锁定条件,以便访问是原子的。
    3. Wait()上的
    4. AtomicBoolean,以便线程共享他们正在等待的监视器(以及notifyAll())。

答案 2 :(得分:0)

您可以使用更简单的方法来同步线程。

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