同一个线程能够在同一个对象上执行两个同步方法 [英] Same thread is able to execute on same objects two synchronized methods

查看:65
本文介绍了同一个线程能够在同一个对象上执行两个同步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,只有一个线程可以在同一个块上的同步方法上执行,但在下面的生产者消费者问题中,我可以同时运行这两种方法.

As I Know only one thread can execute on a synchronize method on same block but in below producer consumer problem I am able to run both the methods.

示例代码

import java.util.concurrent.CountDownLatch;

public class VIV {

    public static void main(String[] args) throws Exception {
        Number no = new Number();

        //Same Object is passed
        Even ev = new Even(no, 10);
        Odd od = new Odd(no, 10);

        Thread oddThraed = new Thread(od,"ODD");
        oddThraed.start();

        Thread evenThraed = new Thread(ev,"Even");
        evenThraed.start();
    }
}

class Number {

    int no;
    boolean flag=false;

    public synchronized int getEvenNo() {
        System.out.println("In Even Method");
        // wait block so no other thread can enter on same object synchronized method
        try{
            wait();
        }catch (Exception e) {
            // TODO: handle exception
        }

        if(!flag) {
            try {
                Thread.sleep(1000);
            }catch (Exception e) {
                // TODO: handle exception
            }
        }   

        no=no+1;
        System.out.println(Thread.currentThread().getName()+":"+no);
        flag=false;
        notify();
        return no;
    }

    public synchronized int getOddNo() {
        System.out.println("In ODD Method");
        // wait block so no other thread can enter on same object synchronized method
        try{
            wait();
        }catch (Exception e) {
            // TODO: handle exception
        }

        if(flag) {
            try{
               wait();
            }catch (Exception e) {
                // TODO: handle exception
            }
        }   
        no = no+1;
        System.out.println(Thread.currentThread().getName()+":"+no);
        flag=true;
        notify();
        return no;
    }

}

class Even implements Runnable {
    Number num;
    int noOfTime;

    Even(Number no, int noOfTime) {
        this.num=no;
        this.noOfTime=noOfTime;
    }

    public void run() {
        for(int i=0;i<noOfTime;i++) {
            num.getEvenNo();
        }   
    }
}

class Odd  implements Runnable {

    Number num;
    int noOfTime;

    Odd(Number no, int noOfTime) {
        this.num=no;
        this.noOfTime=noOfTime;
    }   

    public void run() {
        for(int i=0;i<noOfTime;i++) {
            num.getOddNo();
        }   
    }
}

输出:

  1. 在奇数方法中
  2. 偶数方法

As 仅创建一个 Number 对象并将其传递给调用其两种不同同步方法的其他类.两种方法都在等待之后打印消息.

As Only one Number object is created and passed to other classes which are invoking on its two different synchronized methods. Both methods are printing the message after that waiting .

推荐答案

两个方法同时执行的原因是wait()方法释放锁.一旦您的 synchronized 方法调用了 wait(),锁就会返回,另一个线程可以调用同一个对象上的另一个 synchronized 方法.不要以这种方式在 synchronized 方法中调用 wait()

The reason that both methods get executed at the same time is that the wait() method releases the lock. Once your synchronized method calls wait(), the lock is given back, and another thread can invoke another synchronized method on the same object. Don't call wait() inside a synchronized method in this way!

wait() 调用也是您陷入死锁的原因.这是正在发生的事情:

The wait() calls are also the reason that you're getting deadlock. This is what is happening:

  1. odd 方法获取锁并开始执行.
  2. odd 方法打印它的第一条消息.
  3. odd 方法调用 wait(),释放锁并等待通知.
  4. even 方法现在可以获取已释放的锁.
  5. even 方法打印它的第一条消息.
  6. even 方法调用 wait(),释放锁并等待通知.
  1. The odd method acquires the lock and starts executing.
  2. The odd method prints its first message.
  3. The odd method invokes wait(), which releases the lock and waits to be notified.
  4. The even method can now acquire the lock that's been released.
  5. The even method prints its first message.
  6. The even method invokes wait(), which releases the lock and waits to be notified.

此时,您处于两个 synchronized 方法的中间(因为 wait() 释放了锁),并且您处于死锁状态(因为这两个方法正在等待).

By this point, you're in the middle of both synchronized methods (because wait() releases the lock), and you're deadlocked (because both methods are waiting).

不要调用 wait() 除非你很确定这是你需要的.如果你的 wait() 只是为了让它等待看同步是否可以被破坏,你可以尝试使用 Thread.sleep() 代替,它会暂停而不释放任何锁.通常将相关方法或块声明为 synchronized 就足够了,不需要任何 wait/notify.

Don't call wait() unless you're quite sure that's what you need. If your wait() is there just to keep it waiting to see if the synchronization can be broken, you might try Thread.sleep() instead, which will pause without releasing any locks. Usually it's enough to declare the relevant methods or blocks as synchronized without needing any wait / notify.

(顺便说一句,有一个叫做Number的类不是一个好主意,因为这是一个标准的JDK类.它是Double的超类,整数,等等.)

(By the way, it's not a good idea to have a class called Number, because this is a standard JDK class. It's the superclass of Double, Integer, and so on.)

这篇关于同一个线程能够在同一个对象上执行两个同步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆