什么是共享状态,竞争条件何时发生?

时间:2013-01-30 18:19:43

标签: java thread-safety

    //$Id$    
import java.util.logging.Level;
import java.util.logging.Logger;

public class ThreadSafe {

    public static final Logger LOGGER = Logger.getLogger(ThreadSafe.class.getName());

    public static int  random(int num){
        LOGGER.log(Level.INFO,"Entered Num : {0}",num);
        try {
            Thread.sleep(5);
        } catch (InterruptedException e) {
            LOGGER.log(Level.INFO,"Interrupted Exception");
        }
        return num + 2;
    }

    public static void main(String[] args){
        for(int threads=1;threads<100;threads++){
            final int number = threads;
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int val = ThreadSafe.random(number);
                    System.out.println("Excepted Value = " + (number+2) + " Returned Value = " + val);
                }

            },"Thread : "+threads);
            thread.start();
        }
    }


}

输出:

30 Jan, 2013 11:41:26 PM com.zoho.learn.test.ThreadSafe random
INFO: Entered Num : 2
30 Jan, 2013 11:41:26 PM com.zoho.learn.test.ThreadSafe random
INFO: Entered Num : 45
30 Jan, 2013 11:41:26 PM com.zoho.learn.test.ThreadSafe random
INFO: Entered Num : 44
30 Jan, 2013 11:41:26 PM com.zoho.learn.test.ThreadSafe random
INFO: Entered Num : 43
30 Jan, 2013 11:41:26 PM com.zoho.learn.test.ThreadSafe random
INFO: Entered Num : 42
30 Jan, 2013 11:41:26 PM com.zoho.learn.test.ThreadSafe random
INFO: Entered Num : 38
Excepted Value = 47 Returned Value = 47
30 Jan, 2013 11:41:26 PM com.zoho.learn.test.ThreadSafe random
INFO: Entered Num : 41
Excepted Value = 44 Returned Value = 44
Excepted Value = 46 Returned Value = 46

我除了同时访问同一方法的多线程外。如果我们同时访问静态方法会发生什么?

当竞争状况发生时?

什么是共享状态?

如果我错了,请纠正我。

3 个答案:

答案 0 :(得分:3)

同时执行的唯一一段代码(run()除外)是:

public static int  random(int num){
    LOGGER.log(Level.INFO,"Entered Num : {0}",num);
    try {
        Thread.sleep(5);
    } catch (InterruptedException e) {
        LOGGER.log(Level.INFO,"Interrupted Exception");
    }
    return num + 2;
}

剥离日志记录(在每个健全的实现中都是线程安全的),休眠(只影响当前线程)和异常处理,这就是你剩下的:

public static int  random(int num){
    return num + 2;
}

每个线程不仅num参数是私有的(每个线程都有自己的堆栈内存),而且它永远不会被修改。因此,您的计划中不会出现竞争条件。

代码中没有共享状态(全局变量),只有当一个线程修改共享数据而其他线程读取它时,才可能出现竞争条件。

你想看到竞争条件?你走了!

private volatile int globalNum;

public static int  random(int num){
    globalNum = num;
    try {
        Thread.sleep(5);
    } catch (InterruptedException e) {
        LOGGER.log(Level.INFO,"Interrupted Exception");
    }
    return globalNum + 2;
}

灾难的最后几秒:

  1. 主题1进入random(42),分配globalNum = 42并进入睡眠状态

  2. 主题2输入random(17),分配globalNum = 17并进入睡眠状态

  3. 线程1唤醒读取当前值globalNum17)并按预期返回19而不是44

    < / LI>

    另见

答案 1 :(得分:0)

  

我除了多线程同时访问同一个方法外。

访问相同方法的多个线程不是问题。只有当多个线程访问相同的状态时,才会存在竞争条件。您的计划中没有共享状态,因此没有竞争条件。

答案 2 :(得分:0)

多线程在访问公共资源时变得至关重要 这可以是一个静态变量,一个线程更改而另一个线程读取。

局部变量不受影响,也不受方法调用的影响,因为每个线程都有自己的局部变量。

你没有在踏板之间共享共同的资源。