关于Java同步机制中synchronized同步方法
Java的同步机制中被synchronized关键字修饰的有两种,一种是同步块,另一种是同步方法。现在直说同步方法
在同步方法中,被synchronized关键字修饰的方法的作用域有两种:
a. 作用域是某个实例内,synchronized Method(){ }可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象中有多个synchronized方法,只要一个线程访问了其中一个synchronized方法,其他线程不能同时访问这个对象中任何一个synchronized方法)。这时不同的对象实例中的synchronized方法是互不干扰的,也就是说,其他线程照样可以访问相同类的另一个对象实例中的synchronized方法。
也就是说,只被synchronized修饰的方法,作用域只在单个对象中,进程的同步机制只在单个对象中,不同对象中的synchronized方法是不相互干扰的
Eg:
public class ThreadSafeTest extends Thread implements Runnable { private static int num = 1; public ThreadSafeTest(String name) { setName(name); } public void run() { sell(getName()); } private synchronized void sell(String name){ if (num > 0) { System.out.println(name + ": 检测票数大于0"); System.out.println(name + ": \t正在收款(大约5秒完成)。。。"); try { Thread.sleep(5000); System.out.println(name + ": \t打印票据,售票完成"); num--; printNumInfo(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(name+": 没有票了,停止售票"); } } private void printNumInfo() { System.out.println("系统:当前票数:" + num); if (num < 0) { System.out.println("警告:票数低于0,出现负数"); } } public static void main(String args[]) { try { new ThreadSafeTest("售票员李XX").start(); Thread.sleep(2000); new ThreadSafeTest("售票员王X").start(); } catch (InterruptedException e) { e.printStackTrace(); } } }
上述代码中同步方法只被synchronized修饰,所以这个同步方法只能用于单个对象中。
运行的结果是:并没有达到线程间同步的目的
b. 作用域是某个类的范围,这个时候方法就需要synchronized static来修饰了。synchronized static Method(){ }用于防止多个线程同时访问这个类中的synchronized static方法,它是对类的所有对象实例起作用。
也就是说,某个方法被synchronized static修饰后,这个方法就对所有的对象实例起作用了,只要有一个对象实例调用了该方法,其他的对象实例只能等该方法解锁后才能调用该方法,从而起到线程之间的同步问题。
Eg:
把上述代码的sell()方法改为synchronized static,printNumInfo()改为static后就可以实现线程同步问题了
public class ThreadSafeTest extends Thread implements Runnable { private static int num = 1; public ThreadSafeTest(String name) { setName(name); } public void run() { sell(getName()); } private synchronized static void sell(String name){ if (num > 0) { System.out.println(name + ": 检测票数大于0"); System.out.println(name + ": \t正在收款(大约5秒完成)。。。"); try { Thread.sleep(5000); System.out.println(name + ": \t打印票据,售票完成"); num--; printNumInfo(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(name+": 没有票了,停止售票"); } } private static void printNumInfo() { System.out.println("系统:当前票数:" + num); if (num < 0) { System.out.println("警告:票数低于0,出现负数"); } } public static void main(String args[]) { try { new ThreadSafeTest("售票员李XX").start(); Thread.sleep(2000); new ThreadSafeTest("售票员王X").start(); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行的结果达到了线程间的同步
注意:synchronized关键字不能继承,也就是说,基类的方法synchronized f(){ }在继承类中不自动生成synchronized f() { },而变成了f() { }。继承类需要你显示的制定他的某个方法是synchronized方法。