同一个类的不同对象的同步方法

24 浏览
0 Comments

同一个类的不同对象的同步方法

我有一个类 c ,其中有3个同步函数 m1 m2 m3 。我创建了3个不同的实例 c1 c2 c3 ,分别在不同的线程 t1 t2 t3 上运行。如果 t1 访问 m1 t2 t3 能访问 m1 吗?

0
0 Comments

当同一个类的不同对象的同步方法被多个线程同时调用时,可能会出现并发问题。具体来说,如果同步方法是静态方法,它们会在类对象上同步,这样就不可能交错执行。然而,如果同步方法是非静态方法,它们会在实例对象上同步,这样就可能发生交错执行。下面的示例代码可以说明这种行为。

import java.util.ArrayList;
import java.util.List;
class Main {
  public static void main(String... args) {
    List threads = new ArrayList();
    System.out.println("----- First Test, static method -----");
    for (int i = 0; i < 4; ++i) {
      threads.add(new Thread(() -> {
        Main.m1();
      }));
    }
    for (Thread t : threads) {
      t.start();
    }
    for (Thread t : threads) {
      try {
        t.join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("----- Second Test, non-static method -----");
    threads.clear();
    for (int i = 0; i < 4; ++i) {
      threads.add(new Thread(() -> {
        new Main().m2();
      }));
    }
    for (Thread t : threads) {
      t.start();
    }
    for (Thread t : threads) {
      try {
        t.join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("----- Third Test, non-static method, same object -----");
    threads.clear();
    final Main m = new Main();
    for (int i = 0; i < 4; ++i) {
      threads.add(new Thread(() -> {
        m.m2();
      }));
    }
    for (Thread t : threads) {
      t.start();
    }
    for (Thread t : threads) {
      try {
        t.join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
  public static synchronized void m1() {
    System.out.println(Thread.currentThread() + ": starting.");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println(Thread.currentThread() + ": stopping.");
  }
  public synchronized void m2() {
    System.out.println(Thread.currentThread() + ": starting.");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println(Thread.currentThread() + ": stopping.");
  }
}

在上述代码中,我们定义了一个主类Main,其中包含了一个静态方法m1和一个非静态方法m2。在主函数中,我们分别进行了三个实验。第一个实验是调用静态方法m1,由于同步是在类对象上进行的,因此不可能交错执行。第二个实验是调用非静态方法m2,由于同步是在实例对象上进行的,所以可能会交错执行。第三个实验是在同一个实例对象上调用非静态方法m2,由于同步是在实例对象上进行的,所以可能会交错执行。

这种问题的解决方法是使用同步关键字synchronized来修饰方法,以确保同一时间只有一个线程可以访问该方法。对于静态方法,可以使用类对象进行同步;对于非静态方法,可以使用实例对象进行同步。这样可以避免并发问题的发生。

更多详细信息,请参阅[Oracle官方文档](https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html)。

0