Synchronized学习
Syncronized的作用:
- 能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。(有一把锁,持有锁的线程才能执行该段代码)
Syncronized的地位:
- Synchronized是java的关键字。
- 是最基本的互斥同步手段。
用法:
- 对象锁,包括方法锁和同步代码块锁。
- 类锁,指synchronized修饰静态的方法或指定锁为Class对象。
对象锁
- 代码块形式要手动指定锁对象
- 方法锁形式,synchronized修饰普通方法,锁对象默认为this
未加Synchronized关键字:
package syncStu; public class BlockSyncStu implements Runnable{ static BlockSyncStu blockSyncStu= new BlockSyncStu(); @Override public void run() { System.out.println("我是对象锁的代码块形式。我叫:"+ Thread.currentThread().getName() ); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 运行结束" ); } public static void main(String[] args) { Thread thread1 = new Thread(blockSyncStu,"1111"); Thread thread2 = new Thread(blockSyncStu,"2222"); thread1.start(); thread2.start(); while ( thread1.isAlive() || thread2.isAlive() ) {} System.out.println("finished"); } }
/*未加Synchronized关键字 :输出 线程1线程2一起执行run方法*/ 我是对象锁的代码块形式。我叫:2222 我是对象锁的代码块形式。我叫:1111 2222 运行结束 1111 运行结束 finished
加Synchronized代码块:
package syncStu; public class BlockSyncStu implements Runnable{ static BlockSyncStu blockSyncStu= new BlockSyncStu(); @Override public void run() { synchronized (this) { System.out.println("我是对象锁的代码块形式。我叫:"+ Thread.currentThread().getName() ); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 运行结束" ); } } public static void main(String[] args) { Thread thread1 = new Thread(blockSyncStu,"1111"); Thread thread2 = new Thread(blockSyncStu,"2222"); thread1.start(); thread2.start(); while ( thread1.isAlive() || thread2.isAlive() ) {} System.out.println("finished"); } }
我是对象锁的代码块形式。我叫:1111 1111 运行结束 我是对象锁的代码块形式。我叫:2222 2222 运行结束 finished
执行和结束之间都间隔了3S。
- 这里的this锁对象,可以使用Object类型的对象代替,有多个目标块需要竞争同一资源的时候,这几个目标块上的对应参数一致,即可。
Synchronized做方法锁:
package syncStu; public class MethodStu implements Runnable{ static BlockSyncStu blockSyncStu= new BlockSyncStu(); @Override public void run() { method(); } public synchronized void method() { System.out.println("我是对象锁的方法修饰符形式。我叫:"+ Thread.currentThread().getName() ); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 运行结束" ); } public static void main(String[] args) { Thread thread1 = new Thread(blockSyncStu,"1111"); Thread thread2 = new Thread(blockSyncStu,"2222"); thread1.start(); thread2.start(); while ( thread1.isAlive() || thread2.isAlive() ) {} System.out.println("finished"); } }
我是对象锁的代码块形式。我叫:1111 1111 运行结束 我是对象锁的代码块形式。我叫:2222 2222 运行结束 finished
这个也是依次执行。
类锁
概念:
- java类可能有很多个对象,但是只有一个Class对象。本质上类锁是一个概念,就是同一时刻只能被一个对象拥有。其他对象会被阻塞。
形式:
- synchronized加在static方法上
- synchronized(.class)代码块
package syncStu; public class ClassStaticStu implements Runnable{ //实例1 static ClassStaticStu blockSyncStu1= new ClassStaticStu(); //实例2 static ClassStaticStu blockSyncStu2= new ClassStaticStu(); @Override public void run() { method(); } /** * 未加了static关键字 */ public synchronized void method() { System.out.println("我是对象锁的方法修饰符形式。我叫:"+ Thread.currentThread().getName() ); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 运行结束" ); } public static void main(String[] args) { Thread thread1 = new Thread(blockSyncStu1,"1111"); Thread thread2 = new Thread(blockSyncStu2,"2222"); thread1.start(); thread2.start(); while ( thread1.isAlive() || thread2.isAlive() ) {} System.out.println("finished"); } }
我是对象锁的方法修饰符形式。我叫:1111 我是对象锁的方法修饰符形式。我叫:2222 2222 运行结束 1111 运行结束 finished
这种是两个实例对应的线程,并没有被synchronized限制,是一起执行的。
把method()方法变为静态方法:
package syncStu; public class ClassStaticStu implements Runnable{ //实例1 static ClassStaticStu blockSyncStu1= new ClassStaticStu(); //实例2 static ClassStaticStu blockSyncStu2= new ClassStaticStu(); @Override public void run() { method(); } /** * 加了static关键字 */ public static synchronized void method() { System.out.println("我是对象锁的方法修饰符形式。我叫:"+ Thread.currentThread().getName() ); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 运行结束" ); } public static void main(String[] args) { Thread thread1 = new Thread(blockSyncStu1,"1111"); Thread thread2 = new Thread(blockSyncStu2,"2222"); thread1.start(); thread2.start(); while ( thread1.isAlive() || thread2.isAlive() ) {} System.out.println("finished"); } }
我是对象锁的方法修饰符形式。我叫:1111 1111 运行结束 我是对象锁的方法修饰符形式。我叫:2222 2222 运行结束 finished
这种的静态方法上加了synchronized就可以。
--Java高并发之魂:synchronized深度解析 https://www.imooc.com/learn/1086