synchronized关键字可以使得被修饰的对象(此对象非实例化对象)在同一时间只能被同一个线程访问。 是一个非公平锁,即谁先抢到是谁的。
一、修饰方法 我们启动两个线程去分别执行同一个类的两个对象中的f1方法,观察现象: 1、当synchronized修饰非静态方法时,控制台将每0.5秒输出两次线程名。 2、当synchronized修饰静态方法时,控制台将每0.5秒输出一次线程名。 也就是说
修饰非静态方法:争夺的是调用此方法的对象。修饰静态方法:争夺的是调用此方法的对象的类(静态的属于类)。 class syn_Test { public synchronized static void f1() throws InterruptedException { System.out.println(Thread.currentThread().getName()); Thread.sleep(500); } } class ceshi { public static void main(String[] argv) throws Exception { syn_Test t1 = new syn_Test(); syn_Test t2 = new syn_Test(); new Thread(new Runnable() { @Override public void run() { try { while (true) { t1.f1(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { while (true) { t2.f1(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } }二、修饰代码块 我们启动四个线程去分别执行同一个类的两个对象中的f1、f2方法,观察现象:
很抱歉让您做了一次阅读理解
1、当synchronized修饰的代码块内为this时,控制台将每0.5秒输出两次线程名。 2、当synchronized修饰的代码块内为类的class对象时控制台将每0.5秒输出一次线程名。 也就是说
括号内为this时争夺的是调用此方法的对象括号内为类的class对象时争夺的是调用此方法的对象的类。 class syn_Test { public void f1() throws InterruptedException { synchronized (testTiaoJianSuo.class) { System.out.println(Thread.currentThread().getName()); Thread.sleep(500); } } public void f2() throws InterruptedException { synchronized (this) { System.out.println(Thread.currentThread().getName()); Thread.sleep(500); } } } class ceshi { public static void main(String[] argv) throws Exception { // 实例化两对象 syn_Test t1 = new syn_Test(); syn_Test t2 = new syn_Test(); // 启动四个进程分别执行两对象的四个方法 new Thread(new Runnable() { @Override public void run() { try { while (true) { t1.f1(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { while (true) { t1.f2(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { while (true) { t2.f1(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { while (true) { t2.f2(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } }三、除此之外还有一个很有意思的问题:
为什么在 static synchronized 修饰的方法中为什么不能调用notify()与notifyall()方法?
我想够了挺久的,最后发现
public final native void notify(); public final native void notifyAll();这俩没有用static修饰。