好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

彻底搞懂Java多线程(二)

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,没加锁就释放了锁,就会抛出异常,就会将业务代码中的异常吞噬掉

查看更多关于彻底搞懂Java多线程(二)的详细内容...

  阅读:9次