Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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中的多线程(两个线程广泛使用notify()和wait()_Java_Multithreading_Notify - Fatal编程技术网

java中的多线程(两个线程广泛使用notify()和wait()

java中的多线程(两个线程广泛使用notify()和wait(),java,multithreading,notify,Java,Multithreading,Notify,当我尝试运行以下程序时,在这段代码中对notify()的第一次调用中有一个非法MonitorStateException: synchronized (c) { try { notify(); .... 这让我有点发火:当对象(c)已经在同步块中,并且检查相同的锁时,代码怎么可能没有锁呢 请不要介意过度使用notify()和wait(),看起来有些奇怪。我知道有不同的(更有效的)实现可以执行相同的任务,但现在我正在试图弄清楚为什么这个特定的实现不起作用

当我尝试运行以下程序时,在这段代码中对notify()的第一次调用中有一个非法MonitorStateException:

synchronized (c) {
    try {
        notify();
        ....
这让我有点发火:当对象(c)已经在同步块中,并且检查相同的锁时,代码怎么可能没有锁呢

请不要介意过度使用notify()和wait(),看起来有些奇怪。我知道有不同的(更有效的)实现可以执行相同的任务,但现在我正在试图弄清楚为什么这个特定的实现不起作用

完整代码如下:

  class J implements Runnable {

        public static void main(String[] x) {
            Calc calc = new Calc();
            J j = new J(calc);
            Thread t1 = new Thread(j, "one");
            Thread tCalc = new Thread(calc, "Calc");
            tCalc.start();
            t1.start();
        }
        Calc c;
        public J(Calc c) {
            this.c = c;
        }

        public void run() {
            synchronized (c) {
                try {
                    notify();
                    c.wait();
                } catch (InterruptedException e) {

                }
                System.out.println(Thread.currentThread().getName() + ": x = "
                        + c.getX());
                notify();
            }
        }
    }

    class Calc implements Runnable {

        private int x;

        public int getX() {
            return x;
        }

        public void run() {
            synchronized (this) {

                for (int x = 1; x <= 11111; x *= (x + x)) {
                    this.x += x;
                    try {
                        notify();
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                notify();
            }
        }
    }
J类实现可运行{
公共静态void main(字符串[]x){
Calc Calc=新的Calc();
J=新J(计算);
螺纹t1=新螺纹(j,“一”);
线程tCalc=新线程(计算,“计算”);
tCalc.start();
t1.start();
}
钙;
公共J(计算){
这个.c=c;
}
公开募捐{
已同步(c){
试一试{
通知();
c、 等待();
}捕捉(中断异常e){
}
System.out.println(Thread.currentThread().getName()+“:x=”
+c.getX());
通知();
}
}
}
类Calc实现了Runnable{
私人INTX;
公共int getX(){
返回x;
}
公开募捐{
已同步(此){

对于(intx=1;x,您正试图通知一个线程,该线程正在等待一个当前未持有的锁。
错误是正确的。您在对象c上有一个锁,然后通知其他线程当前对象上的锁。

您试图通知一个线程,该线程正在等待一个当前未持有的锁。
synchronized (c) {
    try {
        notify();
        ....
该错误是正确的。您在对象c上有一个锁,然后通知其他线程当前对象上的锁

synchronized (c) {
    try {
        notify();
        ....
您正在锁定对象
c
,但正在通知对象
。一个好的做法是始终指定将来显式打开的对象
wait()
notify()
。您应该执行以下操作:

synchronized (c) {
    try {
        c.notify();
        ....
或:

看起来你实际上是想处理两个锁。如果是这样的话,你应该做如下的事情

synchronized (c) {
    try {
        synchronized (this) {
            this.notify();
        }
        c.wait();
务必确保始终先锁定
c
,然后再锁定
,否则会死锁

您正在锁定对象
c
,但正在通知对象
。一个好的做法是始终指定将来显式打开的对象
wait()
notify()
。您应该执行以下操作:

synchronized (c) {
    try {
        c.notify();
        ....
或:

看起来你实际上是想处理两个锁。如果是这样的话,你应该做如下的事情

synchronized (c) {
    try {
        synchronized (this) {
            this.notify();
        }
        c.wait();

务必确保始终先锁定
c
,然后再锁定
,否则会死锁。

执行以下操作的方法很复杂

ExecutorService printer = Executors.newSingleThreadExecutor();

int x2 = 0;
for (int x = 1; x <= 11111; x *= (x + x)) {
    x2 += x;
    final int x3 = x2;
    printer.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": x = " + x3);
        }
    });
}
printer.shutdown();
ExecutorService printer=Executors.newSingleThreadExecutor();
int x2=0;

对于(intx=1;x来说,您所拥有的是执行以下操作的复杂方式

ExecutorService printer = Executors.newSingleThreadExecutor();

int x2 = 0;
for (int x = 1; x <= 11111; x *= (x + x)) {
    x2 += x;
    final int x3 = x2;
    printer.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": x = " + x3);
        }
    });
}
printer.shutdown();
ExecutorService printer=Executors.newSingleThreadExecutor();
int x2=0;

对于(int x=1;x Correct-具体地说,
notify();
表示
this.notify();
,而不是
c.notify();
。您需要
synchronize(this)
调用
notify();
,就我所知(不知何故我知道这是不对的,但不完全确定为什么)在类J中同步(c)并同步(this)在类Calc中,本质上是相同的对象锁-因为类J有一个实例字段Calc。在主类Calc中,很明显只有一个实例,这是在类J被构造时传递的。是的,它是相同的对象,但这不是问题。问题是在这段代码中:synchronized(c){try{notify();…您拥有c的锁,然后调用j.notify(),这将导致抛出异常Ep,多亏格雷在下面的评论,我已经解决了所有问题。我的问题是,我读的书强调了notify()的使用,而不是specificularObject.notify()(因为它关注的是同步方法而不是块)这些细微差别对我来说并不完全清楚。谢谢你的澄清!正确-具体地说,
notify();
的意思是
this.notify();
,而不是
c.notify();
。在我看来,你需要
同步(this)
才能调用
notify();
(不知何故,我知道这是不对的,但不完全确定为什么)在类J中同步(c)和同步(这个)在类Calc中,本质上是相同的对象锁-因为类J有一个实例字段Calc。在主类Calc中,很明显只有一个实例,这是在类J被构造时传递的。是的,它是相同的对象,但这不是问题。问题是在这段代码中:synchronized(c){try{notify();…您拥有c的锁,然后调用j.notify(),这将导致抛出异常Ep,多亏格雷在下面的评论,我已经解决了所有问题。我的问题是,我读的书强调了notify()的使用,而不是specificularObject.notify()(因为它关注的是同步方法而不是块)这些细微差别对我来说并不完全清楚。谢谢你的澄清!谢谢格雷,现在在你的第一行评论之后,我看清楚了。我错误地认为,当你输入一个同步块,并将一个指定的对象作为锁时,只要调用notify(),它就会自动得到支持