【问题标题】:synchronized methods executing simulaneously同步方法同时执行
【发布时间】:2021-10-19 02:08:00
【问题描述】:

根据 synchronized 关键字,如果应用于方法,则它会获取对象锁,并且具有相同实例的多个方法将无法同时执行这些方法。

但在下面的示例中,执行是同时发生的。 请看一下:-

public class ncuie extends Thread{

    int b;
    ncuie(int a){
        b=a;
    }
    
    public synchronized void abc() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            System.out.println("thread 1 "+i);
        }
    }
    
    public synchronized void pqr() throws InterruptedException {

        for (int i = 0; i < 10; i++) {
            System.out.println("thread 2 "+i);
        }
        
    }
    
    public void run() {
        
        try {
            if(b==5) {
            abc();
            }
            if(b==10) {
            pqr();
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
    public static void main(String[] args) {
        Thread t=new ncuie(5);
        Thread t1=new ncuie(10);
        t.start();
        t1.start();
    }
}

根据输出,有时执行线程 1,有时执行线程 2。 理想情况下,只有一个线程应该获得锁并完成它的执行,然后才应该启动第二个。

输出:-

thread 1 0
thread 1 1
thread 2 0
thread 2 1
thread 2 2
thread 1 2
thread 1 3
thread 1 4
thread 1 5
thread 1 6
thread 1 7
thread 1 8
thread 2 3
thread 2 4
thread 2 5
thread 2 6
thread 1 9
thread 2 7
thread 2 8
thread 2 9

【问题讨论】:

  • 发生这种情况是因为您创建了类ncuie 的多个实例。锁是每个对象。第一个线程锁定一个对象,第二个线程锁定另一个对象。
  • 那么我们应该如何创建多个具有相同实例的线程来实现正确的同步呢?

标签: java multithreading thread-safety synchronized java.util.concurrent


【解决方案1】:

synchronizedthis 上获得锁定。您有两个 ncuie 类的实例,因此将它们同时锁定是非常好的。

要解决它,您需要在线程之间共享一些实例。我建议创建新的Object 并将其传递给 constrictor。

【讨论】:

    【解决方案2】:

    如果某些方法更改内部状态以致在同一实例上运行的其他方法会遇到麻烦,您通常会在您的实例上进行同步。通过在非静态方法上使用 synchronized 关键字或编写 synchronized(this) {...},可以在当前实例 (this) 上进行同步。

    如果您的方法以这样一种方式更改状态,以至于即使在类的不同实例上操作的方法也会受到影响,您可以在类对象上进行同步。你可以写synchronized(MyClass.class) {...}

    如果您有静态方法需要与同一类的其他静态方法同步,您可以通过在静态方法上使用synchronized 关键字来获取类对象上的同步。

    请注意,实例级同步和类级同步是完全独立的,这意味着,当类同步的方法运行时,实例同步的方法不会被阻塞。

    在您的情况下,您在实例上进行了同步,并且您有两个不同的实例,因此它们不会相互阻塞。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-10
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-21
      • 2017-10-23
      • 2021-09-25
      相关资源
      最近更新 更多