Java同步混乱

用户名

很抱歉,如果这是非常明显的,或者已经在其他地方得到解答。我什么都找不到。我有以下代码:

public class SimpleThread extends Thread {
    public static Integer sharedVal = 0;
    public SimpleThread() {

    }
    @Override
    public void run() {
       while(true) {           
           iterator();
       }
    }

    public void theSleeper() {
        System.out.println("Thread: " + this.getId() + " is going to sleep!");
        try {
            this.sleep(5000);
        } catch(Exception e) {

        }
    }

    public void iterator() {
        synchronized(sharedVal)  {
            System.out.println("Iterating sharedVal in thread: " + this.getId());
            sharedVal++;
            System.out.println(sharedVal);
            theSleeper();
            System.out.println("Thread : " + getId() + " is done sleeping, trying to iterate again..."); 
        }
    }
}

我创建了此SimpleThread类的两个实例,并执行run方法。我希望看到类似的东西:线程9递增...线程9睡眠...(5秒后)线程10递增....线程10睡眠...。我之所以这样,是因为我锁定了迭代器方法,因此一次只能有一个线程可以输入它。相反,发生的情况是两个线程都递增,然后都等待5秒钟。这将永远重复。我在这里想念什么,以便得到预期的行为?非常感谢!

编辑:我做了一个新的公共静态变量:公共静态对象theLock = new Object()。现在,在迭代器方法中,我进行了sync(theLock)。现在的输出比我预期的要多,因为锁定永远不会改变。但是,现在只有线程9才能进入该方法。线程10似乎饿了,再也没有转过身。这似乎很奇怪。这不仅是几次,而且总是线程9不断迭代和休眠。我认为应该是9、10、9、10,或者是9、10、10、10、9、10、9、9、10等随机分布。

EDIT2:我知道现在发生了什么。线程9具有锁。线程10尝试进入该函数,但立即被告知等待。函数完成后,可能仍是线程9s转动。然后线程9重新获得该锁,并且循环继续。线程10进行转弯的时间窗口非常小,如果确实转弯,则可能会饿死9。也就是说,将yield()放在iterator()中的同步块之后似乎并没有使它变多。公平。我阅读了有关该方法的注释,并且调度程序实际上可以忽略yield()。

暗霍格

您的问题出在这里:

sharedVal++;

该行,由于自动装箱转换为:

sharedVal = Integer.valueOf(sharedVal.intValue() + 1);

Integer每次运行都会创建一个新对象,因此每次访问该synchronized块时,它都会锁定一个不同的值。

使用专用对象进行同步:

private final static Object LOCK = new Object();

然后将您的同步更改为使用synchronized (LOCK) {...

(您也可以使用getClass()锁定,但是我个人不希望将锁定对象公开。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章