计数器输出到这个多线程代码

时间:2015-03-06 20:55:20

标签: java multithreading

我遇到了关于多线程编程的Java问题(请参阅下面的代码)。基于this question并在StackOverflow上回答,我想我明白为什么会出现死锁。但我不明白的是,如果程序正常工作(即没有死锁),那么foo打印的价值是多少?我以为它会是20(thread1计数到10,thread2计数到10)。有人可以帮我解释一下这种情况(最好以一种简单的方式解释因为我还是线程编程的新手)吗?谢谢。

public class ThreadTest{

  private static class ThreadOne extends Thread{
    private ThreadTwo threadTwo; 
    public int foo = 0;

    public void setThreadTwo(ThreadTwo th){
       threadTwo = th;
    }

    public void run(){
      try{
        for(int i=0;i<10;i++) foo += i;

        synchronized(this){this.notify();};

        synchronized(threadTwo){threadTwo.wait();};

        System.out.print("Foo: " + threadTwo.foo);
      }catch(InterruptedException e){ e.printStackTrace();}    
    }
  }

  private static class ThreadTwo extends Thread{

    private final ThreadOne threadOne;
    public int foo = 0;

    public ThreadTwo(ThreadOne th){
      threadOne = th;
    }

    public void Run(){
       try{
         synchronized(threadOne){threadOne.wait();}
         foo = threadOne.foo;

         for(int i=0;i<10;i++) foo += i;
         synchronized(this){this.notify();};
           }
       catch(InterruptedException e){e.printStackTrace();}    
    }    
  }

  public static void main(){
    ThreadOne th1 = new ThreadOne();
    ThreadTwo th2 = new ThreadTwo(th1);

    th1.setThreadTwo(th2);

    th1.start(); th2.start();
    th1.join(); th2.join();
  } 
}

1 个答案:

答案 0 :(得分:1)

根据您的代码并且没有死锁foo值将为90(如果我没有错误计算)。因为您foo += 1而不是foo += i

编辑:好的,一步一步。

  1. foo = 0
  2. th1th2开始。 th2等待通知。 th1foo增加到最多45
  3. th1通知并开始等待th2。系统会通知th2并开始将foo从45增加到90
  4. th2通知th1。系统会通知th1,并打印th2.foo,即90
  5. 编辑2:正确的方法从2个线程从0到90计数而不进行并发修改是这样的

    public class ThreadTest {
        private static int counter = 0;
    
        private static class Thread1 extends Thread {
            final Object lock;
    
            public Thread1(Object lock) {
                this.lock = lock;
            }
    
            @Override
            public void run() {
                synchronized (lock) {
                    for (int i = 0; i < 10; i++)
                        counter += i;
                }
            }
        }
    
        private static class Thread2 extends Thread {
            final Object lock;
    
            public Thread2(Object lock) {
                this.lock = lock;
            }
    
            @Override
            public void run() {
                synchronized (lock) {
                    for (int i = 0; i < 10; i++)
                        counter += i;
                }
            }
        }
    
        public static void main(String[] args) {
            final Object lock = new Object();
    
            final Thread th1 = new Thread1(lock);
            final Thread th2 = new Thread2(lock);
    
            th1.start();
            th2.start();
    
            try {
                th1.join();
                th2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println("Counter: " + counter);
        }
    }
    

    但是如果你被迫使用waitnotify,那么它会更复杂一些。使用此类的对象作为公共锁而不是对象

    class Locker {
    
            private boolean isLocked = false;
    
            public synchronized void lock() throws InterruptedException {
                while (isLocked) wait();
                isLocked = true;
            }
    
            public synchronized void unlock() {
                isLocked = false;
                notify();
            }
        }
    

    run方法中,我们喜欢这样:

    @Override
    public void run() {
        try {
            locker.lock();
            for (int i = 0; i < 10; i++)
                counter += i;
            locker.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
相关问题