为什么多个线程之间的值没有更新?

时间:2013-10-18 12:04:33

标签: java multithreading

以下程序执行基本的多线程任务。我在一个类中有两个线程。一个线程执行增加值变量的工作,另一个线程检查值并显示消息。

Class Was{
private int ctime;
private int value;
public Thread w,c;

public was(int a) {
    ctime=a;
    w = new Thread(new Runnable() {           
        public void run() { 
            try {
                for(int i=0;i<5;i++) {
                    Thread.sleep(ctime*1000);
                    value++; 
                }
                System.out.printf("\nIncreasing done");
            } catch(InterruptedException e) { 
                System.out.println(e);
            }
    } 
    });

    c = new Thread(new Runnable() {           
        public void run() { 
            try {
                for(;;) {
                    if(value==3) {
                        w.wait();
                        System.out.printf("\nValue reached");
                        w.notify();
                        break;
                    }
                }
            } catch(InterruptedException e) { 
                System.out.println(e);
            }
        } 
    });
}

main class

class Main{
    public static void main(String z[]) {
        Scanner s = new Scanner(System.in);
        int temp;
        System.out.printf("\nEnter the sleeping time in seconds: ");
        temp=s.nextInt();
        was m = new was(temp);
        m.w.start();
        m.c.start();
    }
}

c线程从不告诉已达到该值。我不明白为什么。

3 个答案:

答案 0 :(得分:8)

  

c线程从不告诉已达到该值。我不明白为什么。

在线程之间共享值时,需要使用某种机制来同步保存该值的内存。这可以使用synchronize块来完成,将值标记为volatile,或使用(在这种情况下)AtomicInteger。这是一个good tutorial on the memory consistency

AtomicInteger在这里使用是正确的,因为它允许线程安全地增加。你必须记住,增量是原子操作,因为它实际上是获取,增量和设置。

您的代码看起来像:

private final AtomicInteger value = new AtomicInteger(0);
...
value.incrementAndGet();
...
if (value.get() == 3) ...

另外,正如@Boris所指出的,你有以下代码:

w.wait();
System.out.printf("\nValue reached");
w.notify();

这不会编译,因为您不在synchronized块中。此外,拥有wait()然后notify()是一种奇怪的模式。您可能还想阅读tutorial on guarded blocks

答案 1 :(得分:0)

我对代码,相同要求但不同设计进行了更改。所以我理解的是,线程W和C应该共享同一个监视器,通过该监视器,当其他信号发出时,会通知它。因此,在这种情况下,对象锁定充当监视器。我将同一个Object(lock)实例传递给两个线程,并在该锁上调用wait和notify。它工作正常。     package com.stackoverflow.gin;

public class Main {

    private Object lock = new Object();
    private C c = new C(lock);
    private W w = new W(lock);

    public static void main(String[] args) {
        Main u = new Main();
        u.start();
    }

    public void start() {
        System.out.println("Start");
        c.start();
        w.start();
    }

    public class W extends Thread {
        private Object lock;

        public W(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (;;) {
                    Thread.sleep(1000);
                    System.out.println("Notify C that I have finished work");
                    synchronized (lock) {
                        lock.notify();
                    }
                }
            } catch (Exception e) {
                System.out.println(e.getMessage() + "W");
            }
        }
    }

    public class C extends Thread {
        private int times = 0;
        private Object lock;

        public C(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (;;) {
                    System.out.println("Waiting for W to finish ");
                    synchronized (lock) {
                        lock.wait();
                    }
                    System.out.println("W has notified " + times);
                    times++;
                    if (times == 3) {
                        System.out.println("Every thing is done, lets die to gether");
                        System.exit(0);

                    }
                }
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }

}

答案 2 :(得分:0)

我认为你不能或者应该从其他线程中等待一个线程。它像两辆公共汽车并行运行,一辆公共汽车想在其他公交车上运行。那没有意义。或者它不是一个好的设计。我不知道以下是你在寻找什么,但看看,让我知道。

import java.util.concurrent.atomic.AtomicInteger;

public class Main {

    private Object lock = new Object();
    private C c = new C(lock);
    private W w = new W(lock);
    private AtomicInteger times = new AtomicInteger();

    public static void main(String[] args) {
        Main u = new Main();
        u.start();
    }

    public void start() {
        System.out.println("Start");
        c.start();
        w.start();
    }

    public class W extends Thread {
        private Object lock;

        public W(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(1000);
                    times.set(i + 1);
                    System.out.println("Incremented counter " + times.get());
                }
                synchronized (lock) {
                    System.out.println("Notify C that I have finished work");
                    lock.notify();
                }
            } catch (Exception e) {
                System.out.println(e.getMessage() + "W");
            }
        }
    }

    public class C extends Thread {
        private Object lock;

        public C(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (;;) {
                    if (times.get() == 3) {
                        synchronized (lock) {
                            System.out.println("Now I will wait until W finishes with his work");
                            lock.wait();
                            System.out.println("Ok W is finished with the loop " + times.get() + " lets exit the sytem.");
                            System.exit(0);
                        }
                    }
                }
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }

}