Java的锁

Posted xiatianyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java的锁相关的知识,希望对你有一定的参考价值。

今天练习了Java的多线程,提到多线程就基本就会用到锁
Java通过关键字及几个类实现了锁的机制,这里先介绍下Java都有哪些锁:
 
一、Java实现锁的机制:
Java运行到包含锁的代码时,获取尝试获取对应的锁,如果锁被其他线程占用着,则该线程默认等待,待这个锁得以释放在去获取,进而执行锁中的代码。
注:这里说的尝试获取对应的锁是指当多个线程公用一个锁的时候。
 
二、锁的种类
Java总共就两个锁:对象锁类锁
 
区别:
具体这里分为了对象锁和类锁,是因为锁作用的范围不同,如果多个线程采用的是对象锁,需要要求他们引用同一个对象实例的锁才起作用,一旦一个线程使用的是不同的对象实例,就不受这个锁的干预了,但是类锁不同,类锁对应的是class对象,这个类的所有实例对应一个class对象,所以他们相当于争抢同一个锁。
 
对象锁:
说到对象锁,需要在这了统一一个认识:Java里的所有代码都是对对象执行的操作
其实每个对象都有一个锁,只不过对于没有加锁的代码而言,他们对这个锁视而不见,因为普通代码的执行根本就不依赖锁。
对象锁的具体表现形式是:
  1. 对方法加的锁
  2. 代码块加的锁
 
对方法加的锁长这样:
 1 public synchronized void output1() {
 2     for(int i=0;i<10;i++) {
 3         System.out.println(Thread.currentThread().getName());
 4         try {
 5             Thread.sleep(100);
 6         } catch (InterruptedException e) {
 7             e.printStackTrace();
 8         }
 9     }
10 }
运行结果如下:
技术分享图片
Synchronized test
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
View Code
 
对代码块加的锁长这样:
 1 public void output2() {
 2     for(int i=0;i<1;i++) {
 3         System.out.println(Thread.currentThread().getName() + "---read");
 4     }
 5     synchronized(Synchronized_test.syn) {
 6         for(int i=0;i<10;i++) {
 7             System.out.println(Thread.currentThread().getName() + "--- write");
 8             try {
 9                 Thread.sleep(100);
10             } catch (InterruptedException e) {
11                 e.printStackTrace();
12             }
13         }
14     }
15 }
运行结果如下:
技术分享图片
Synchronized test
thread1---read
thread2---read
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2—write
View Code
 
实现原理:
具体的实现方式是,当程序运行到包含锁的代码的时候,不管是方法还是代码块,线程会拿到锁域里的所有对象的锁。如果有方法调用也会递归式的获取。
 
类锁
类锁一半针对静态代码块或者静态方法。例子这里就不写了,就是相当于在上面两个例子前面加个static关键字。
只要是调用这个类的方法,引用类锁的线程争抢的就都是一把锁。
 
 
三、关于锁的关键字:
synchronized  
注:可以指定方法,可以指定代码块
 
四、实现锁的类
1. ReentrantLock
2. Reentrant?ReadWriteLock
 
这两种锁和synchronized关键字的区别:
  1. ?当锁被其他线程获取,当前线程可以不必阻塞住。
  2. 关键字的方式是由系统自动释放锁,而下面必须要手动操作。
 
ReentranLock的用法
  1. 简单的用法如下,功能同关键字synchronized
 1 @Override
 2 public void run() {
 3     lock.lock();
 4     for(int i=1;i<10;i++) {
 5         System.out.println(Thread.currentThread().getName());
 6         try {
 7             Thread.sleep(100);
 8         } catch (InterruptedException e) {
 9             e.printStackTrace();
10         }
11      }
12     lock.unlock();
13 }
运行结果如下:
技术分享图片
lock test
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
View Code
 
  1. ?实现中断线程
 1 public class Lock_interrupt_test implements Runnable {
 2     private Lock lock = null;
 3     public Lock_interrupt_test() {
 4         lock = new ReentrantLock();
 5     }
 6 
 7     @Override
 8     public void run() {
 9         try {
10             lock.lockInterruptibly();
11             for (int i = 0; i < 10; i++) {
12                 System.out.println(Thread.currentThread().getName());
13                 Thread.sleep(100);
14             }
15         } catch (InterruptedException e1) {
16             e1.printStackTrace();
17         } finally {
18             lock.unlock();
19         }
20 }
21 public static void main(String[] args) {
22     System.out.println("lock interrupt test");
23     Lock_interrupt_test lock_interrupt_test = new 
24 Lock_interrupt_test();
25     Thread thread1 = new Thread(lock_interrupt_test, "thread1");
26     Thread thread2 = new Thread(lock_interrupt_test, "thread2");
27     thread1.start();
28     thread2.start();
29     try {
30         Thread.sleep(400);
31     } catch (InterruptedException e) {
32         e.printStackTrace();
33     }
34     State state1 = thread1.getState();
35     Thread thread = state1.toString().equals("TIMED_WAITING")? 
36 thread1:thread2;
37     System.out.println("interrupt " + thread.getName());
38     thread.interrupt();
39     }
40 }
运行结果如下:
技术分享图片
lock interrupt test
thread1
thread1
thread1
thread1
interrupt thread1
java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at lock_type.Lock_interrupt_test.run(Lock_interrupt_test.java:21)
at java.base/java.lang.Thread.run(Thread.java:844)
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
View Code
 
  1. ?实现检测锁状态
 1 @Override
 2 public void run() {
 3     try {
 4         if (lock.tryLock(400,TimeUnit.MILLISECONDS)) {
 5             System.out.println(Thread.currentThread().getName() + " have get the lock");
 6             for (int i = 1; i < 10; i++) {
 7                 System.out.println(Thread.currentThread().getName());
 8                 try {
 9                    Thread.sleep(100);
10                 } catch (InterruptedException e) {
11                     e.printStackTrace();
12                 }
13             }
14             System.out.println(Thread.currentThread().getName() + " have 
15             return the lock");
16             lock.unlock();
17         }
18         else {
19             for (int i = 1; i < 10; i++) {
20                 System.out.println(Thread.currentThread().getName() + " locking");
21                 try {
22                     Thread.sleep(100);
23                 } catch (InterruptedException e) {
24                     e.printStackTrace();
25                 }
26             }
27         }
28     } catch (InterruptedException e) {
29         e.printStackTrace();
30     }
31 }
运行结果如下:
技术分享图片
lock try test
Thread-0 have get the lock
Thread-0
Thread-0
Thread-0
Thread-0
Thread-1 locking
Thread-0
Thread-1 locking
Thread-0
Thread-1 locking
Thread-0
Thread-1 locking
Thread-0
Thread-1 locking
Thread-0
Thread-1 locking
Thread-0 have return the lock
Thread-1 locking
Thread-1 locking
Thread-1 locking
View Code
 
ReentrantReadWriteLock的用法
实现读写分离锁
 1 @Override
 2 public void run() {
 3     lock.readLock().lock();
 4     for(int i=0;i<10;i++) {
 5         System.out.println(Thread.currentThread().getName() + "---read");
 6         try {
 7             Thread.sleep(100);
 8         } catch (InterruptedException e) {
 9             e.printStackTrace();
10         }
11     }
12     lock.readLock().unlock();
13     lock.writeLock().lock();
14     for(int i=0;i<10;i++) {
15         System.out.println(Thread.currentThread().getName() + "---write");
16         try {
17              Thread.sleep(100);
18         } catch (InterruptedException e) {
19             e.printStackTrace();
20         }
21     }
22     lock.writeLock().unlock();
23 }
运行结果如下:
技术分享图片
lock read write test
thread2---read
thread1---read
thread1---read
thread2---read
thread1---read
thread2---read
thread2---read
thread1---read
thread1---read
thread2---read
thread1---read
thread2---read
thread1---read
thread2---read
thread1---read
thread2---read
thread2---read
thread1---read
thread2---read
thread1---read
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread1---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
thread2---write
View Code

以上是关于Java的锁的主要内容,如果未能解决你的问题,请参考以下文章

Java进阶之光!2021必看-Java高级面试题总结

Java工程师面试题,二级java刷题软件

经验总结:Java高级工程师面试题-字节跳动,成功跳槽阿里!

扫地阿姨看完都学会了!java高级架构师考试

java的锁机制——synchronized

java并发线程锁技术的使用