Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java同步混淆_Java_Concurrency - Fatal编程技术网

Java同步混淆

Java同步混淆,java,concurrency,Java,Concurrency,很抱歉,如果这是非常明显的,或者已经在其他地方得到了回答。我什么也没找到。我有以下代码: public class SimpleThread extends Thread { public static Integer sharedVal = 0; public SimpleThread() { } @Override public void run() { while(true) { itera

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

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秒钟。这种情况永远重复。我在这里遗漏了什么,这样我就能得到预期的行为?非常感谢

编辑:我创建了一个新的公共静态变量:publicstaticobjectthelock=newobject()。现在,在迭代器方法中,我进行了同步(锁定)。输出现在比我预期的要多,因为锁永远不会改变。但是,现在只有线程9进入该方法。线程10似乎正在挨饿,而且从来没有轮到它。这似乎很奇怪。这不仅仅是几次,它总是只是线程9的迭代和休眠。我想应该是9,10,9,10。或者像9,10,10,10,9,10,9,9,10这样的随机分布


EDIT2:我知道现在发生了什么。螺纹9有锁。线程10试图进入函数,但被立即告知等待。函数完成后,可能仍要轮到线程9。然后线程9重新请求锁,循环继续。线程10获得一个回合的时间窗口非常小,如果它确实获得了一个回合,它可能会饿死9。也就是说,在迭代器()中,将yield()放在synchronized块之后似乎不会使它更公平。我阅读了关于该方法的评论,调度器实际上可以忽略yield()

执行增量操作时,您将创建一个新的integer实例和一个新的锁定对象。

您将有效地更改线程在每次迭代中使用的锁定:++on integer创建一个新实例(integer类是不可变的)

执行sharedVal++时,sharedVal成员变量实例正在更改。相反,您可以使用以下语句进行同步:


已同步(SympleThread.class)

您的问题在这里:

sharedVal++;
由于自动装箱,这一行转化为:

sharedVal = Integer.valueOf(sharedVal.intValue() + 1);
它每次运行时都会创建一个新的
Integer
对象,因此每次调用
synchronized
块时,它都会锁定一个不同的值

使用专用对象进行同步:

private final static Object LOCK = new Object();
然后将同步更改为使用
synchronized(LOCK){…


(您也可以使用
getClass()
进行锁定,但我个人不喜欢将锁定对象公开给公众)

@OP:请使用可更改的东西(如StringBuilder)重试(因为StringBuffer是同步的,所以不是StringBuffer)我完全同意,我觉得自己很傻。我不知道为什么整数是不可变的,但这是另一个问题。请查看我的编辑。锁定。等待(5000);事实上,根本不等待。我尝试了锁定和锁定,但我认为您指的是我的锁定。然而,这是交替的9和10。这可能只是睡眠的一个非常严重的时间问题,尽管我想理解为什么10真的会挨饿?很高兴知道事实上…但当它退出同步块时应该发布,对吗?就像我的代码中的迭代器()有一个同步块,其中包含睡眠函数调用。非常感谢您的帮助,这是一个很好的解释。是的,另一个也提到了这一点,感谢您指出此错误。请查看我的编辑是的,感谢您指出我的错误。请查看我的编辑,谢谢!当线程9从睡眠中恢复时,它将释放e锁,然后重新获取它,使线程10没有任何可能性。它唯一的机会是调度程序在锁之间停止线程9,这是不可能的。在迭代之间添加
thread.yield()
,这将使事情变得更公平。是的,我现在看到了这一点,并将其添加到我的第二次编辑中。thread.yield()似乎没有多大帮助,因为调度程序可能忽略了它。尽管如此,我想我现在理解得更多了。非常感谢!自动装箱是一个魔鬼哈哈,似乎它可能会有问题!:)