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 }

运行结果如下:
《Java的锁》
《Java的锁》

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 }

运行结果如下:
《Java的锁》
《Java的锁》

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 }

运行结果如下:
《Java的锁》
《Java的锁》

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 }

运行结果如下:
《Java的锁》
《Java的锁》

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 }

运行结果如下:
《Java的锁》
《Java的锁》

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 }

运行结果如下:
《Java的锁》
《Java的锁》

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

    原文作者:shuxte
    原文地址: https://www.cnblogs.com/xiatianyu/p/9038993.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞