同一个类的不同对象的同步方法
当同一个类的不同对象的同步方法被多个线程同时调用时,可能会出现并发问题。具体来说,如果同步方法是静态方法,它们会在类对象上同步,这样就不可能交错执行。然而,如果同步方法是非静态方法,它们会在实例对象上同步,这样就可能发生交错执行。下面的示例代码可以说明这种行为。
import java.util.ArrayList; import java.util.List; class Main { public static void main(String... args) { Listthreads = 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)。