同步,并不总是如此?

时间:2015-07-06 10:41:01

标签: java multithreading synchronized

synchronized块是否总能正常工作?我现在很困惑!使用synchronized关键字时我错了吗?

代码段如下:

package com.company;

public class Main {

    public static void main(String[] args) {

        for (int i = 0; i < 100; i++) {
            new MyThread().start();
        }
    }
}

class MyThread extends Thread {

    // no atomic
    private static Integer count = 0;

    @Override
    public void run() {
        while (true) {
            synchronized (count) {
            //synchronized (this) {

                if (count > 100)
                    break;

                count++;
                System.out.println("ThreadId:" + currentThread().getId() + ","
                        + "inc MyThread.count to : " + count);
            }

        }
    }
}

结果是:

ThreadId:10,inc MyThread.count to : 2
ThreadId:9,inc MyThread.count to : 2
ThreadId:9,inc MyThread.count to : 4
ThreadId:9,inc MyThread.count to : 5
ThreadId:9,inc MyThread.count to : 6
....

我不知道为什么第10和第9行输出相同的值。

1 个答案:

答案 0 :(得分:9)

你做错了。首先,您在更新的字段上进行同步。在同步块输入时,同步将保留在count变量中的对象上,但您稍后会对其进行修改。因此,如果第二个线程在第一个线程已经增加一个值时启动,则第一个线程将在Integer.valueOf(0)上同步,第二个线程将在Integer.valueOf(1)上同步,并且它们不会等待彼此。

第二个问题是你在Integer上进行同步,缓存的值很小,可能会在程序的完全不同的部分重用,所以你可能最终会等待一些完全不相关的东西。

请注意this上的同步无效,因为this是每个帖子中不同的MyThread对象。

您可以在某些共享对象上修复代码同步,这些共享对象不会因执行而发生更改。为此目的创建一个特殊的锁对象更好:

class MyThread extends Thread {
    private static final Object lock = new Object();
    // no atomic
    private static Integer count = 0;

    @Override
    public void run() {
        while (true) {
            synchronized (lock) {
                ...
            }
        }
    }
}