Java中的锁
Java中的加锁操作有两种:
1.synchronized锁(jvm层的解决方案,也叫监视器锁)
在操作系统的层面使用的是互斥锁(mutex lock)
在Java中放在了对象头中。
2.手动锁Lock
操作锁的流程
1.尝试获取锁 2.使用锁 3.释放锁synchronized锁
package ThreadDeom ; /** * user:ypc; * date:2021-06-12; * time: 14:12; */ class Counter2 { private static volatile int count = 0 ; public void increase () { for ( int i = 0 ; i < 10000 ; i ++) { count ++; } } public void decrease () { for ( int i = 0 ; i < 10000 ; i ++) { count --; } } public int getCount () { return count ; } } public class ThreadDemo19 { public static void main ( String [] args ) throws InterruptedException { //声明锁对象,任何的对象都可以作为锁 Object lock = new Object (); Counter2 counter2 = new Counter2 (); Thread thread1 = new Thread ( new Runnable () { @Override public void run () { //使用锁 synchronized ( lock ) { counter2 . decrease (); } } }); Thread thread2 = new Thread (() -> { synchronized ( lock ) { counter2 . increase (); } }); thread1 . start (); thread2 . start (); thread1 . join (); thread2 . join (); System . out . println ( counter2 . getCount ()); } }结果是:
synchronized使用场景
1.使用synchronized来修饰代码块(可以给任意的对象进行加锁操作) public class ThreadDemo19 { public static void main ( String [] args ) throws InterruptedException { //声明锁对象,任何的对象都可以作为锁 Object lock = new Object (); Counter2 counter2 = new Counter2 (); Thread thread1 = new Thread ( new Runnable () { @Override public void run () { //使用锁 synchronized ( lock ) { counter2 . decrease (); } } }); Thread thread2 = new Thread (() -> { synchronized ( lock ) { counter2 . increase (); } }); thread1 . start (); thread2 . start (); thread1 . join (); thread2 . join (); System . out . println ( counter2 . getCount ()); } }
2.使用synchronized来修饰静态方法(对当前的类进行加锁的操作) package ThreadDeom ; /** * user:ypc; * date:2021-06-12; * time: 14:02; */ class Counter1 { private static volatile int count = 0 ; public void increase () { for ( int i = 0 ; i < 10000 ; i ++) { count ++; } } public void decrease () { for ( int i = 0 ; i < 10000 ; i ++) { count --; } } public int getCount () { return count ; } } public class ThreadDemo18 { public static void main ( String [] args ) throws InterruptedException { Counter1 counter1 = new Counter1 (); Thread thread1 = new Thread ( new Runnable () { @Override public void run () { counter1 . decrease (); } }); Thread thread2 = new Thread (() -> { counter1 . increase (); }); thread1 . start (); thread2 . start (); thread1 . join (); thread2 . join (); System . out . println ( counter1 . getCount ()); } }
3.使用synchronized来修饰普通的方法(对当前类的实例来进行加锁) package ThreadDeom ; /** * user:ypc; * date:2021-06-12; * time: 14:12; */ public class ThreadDemo20 { private static int num = 0 ; private static final int maxSize = 100000 ; public static void main ( String [] args ) throws InterruptedException { ThreadDemo20 threadDemo20 = new ThreadDemo20 (); Thread thread1 = new Thread ( new Runnable () { @Override public void run () { threadDemo20 . increase (); } }); Thread thread2 = new Thread ( new Runnable () { @Override public void run () { threadDemo20 . decrease (); } }); thread1 . start (); thread2 . start (); thread1 . join (); thread2 . join (); System . out . println ( num ); } //给静态的方法进行加锁,被加的锁是当前的对象。 // public synchronized static void increase(){ //给普通的方法进行加锁的操作 public synchronized void increase () { for ( int i = 0 ; i < maxSize ; i ++) { num ++; } } // public synchronized static void decrease(){ public synchronized void decrease () { for ( int i = 0 ; i < maxSize ; i ++) { num --; } } }
synchronized注意事项
1.加锁的时候一定要使用同一把锁对象
Lock类的使用
也叫手动锁
package ThreadDeom ; import java . util . concurrent . locks . Lock ; import java . util . concurrent . locks . ReentrantLock ; /** * user:ypc; * date:2021-06-12; * time: 18:32; */ public class ThreadDemo22 { private static int number = 0 ; private static final int maxSize = 100000 ; public static void main ( String [] args ) { //创建lock锁对象,lock是接口,不能实列化 Lock lock = new ReentrantLock (); Thread thread1 = new Thread (() -> { for ( int i = 0 ; i < maxSize ; i ++) { lock . lock (); try { number ++; } finally { lock . unlock (); } } }); Thread thread2 = new Thread (() -> { for ( int i = 0 ; i < maxSize ; i ++) { lock . lock (); try { number --; } finally { lock . unlock (); } } }); System . out . println ( number ); } }
Lock锁使用的注意事项
lock()操作一定要放在try外面
如果放在try的里面:
1.try中抛出了异常,还没有加锁就释放了finally中的锁的操作了
2.如果放在了try,没加锁就释放了锁,就会抛出异常,就会将业务代码中的异常吞噬掉
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did214577