您当前的位置: 首页 >  Java

并发编程系列教程(10) - 深入Java锁机制

杨林伟 发布时间:2019-10-25 16:34:03 ,浏览量:4

代码已上传到Github,有兴趣的同学可以下载看看:https://github.com/ylw-github/Java-ThreadDemo

1. 重入锁

锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利。

重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。

在JAVA环境下 ReentrantLock(显式锁、轻量级锁)和Synchronized (内置锁、重量级锁)都是 可重入锁。

Synchronized(内置锁、重量级锁):

public class RepeatLockDemo {
    public static class RepeatLockRunnable implements Runnable {
        public synchronized void get() {
            System.out.println("name:" + Thread.currentThread().getName() + " get();");
            set();
        }

        public synchronized void set() {
            System.out.println("name:" + Thread.currentThread().getName() + " set();");
        }

        @Override

        public void run() {
            get();
        }
    }


    public static void main(String[] args) {
        RepeatLockRunnable repeatLockRunnable = new RepeatLockRunnable();
        Thread thread = new Thread(repeatLockRunnable);
        Thread thread1 = new Thread(repeatLockRunnable);
        Thread thread2 = new Thread(repeatLockRunnable);
        thread.start();
        thread1.start();
        thread2.start();
    }
}

运行结果: 在这里插入图片描述

ReentrantLock(显式锁、轻量级锁):

package com.ylw.thread;

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {

    public static class ReentrantLockRunnable implements Runnable{

        ReentrantLock lock = new ReentrantLock();

        public void get() {
            lock.lock();
            System.out.println(Thread.currentThread().getId());
            set();
            lock.unlock();
        }
        public void set() {
            lock.lock();
            System.out.println(Thread.currentThread().getId());
            lock.unlock();
        }

        @Override
        public void run() {
            get();
        }
    }

    public static void main(String[] args) {
        ReentrantLockRunnable reentrantLockRunnable = new ReentrantLockRunnable();
        Thread thread = new Thread(reentrantLockRunnable);
        Thread thread1 = new Thread(reentrantLockRunnable);
        Thread thread2 = new Thread(reentrantLockRunnable);
        thread.start();
        thread1.start();
        thread2.start();
    }

}

运行结果: 在这里插入图片描述

2. 读写锁

相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写,也就是说:读-读能共存,读-写不能共存,写-写不能共存。这就需要一个读/写锁来解决这个问题。Java5在java.util.concurrent包中已经包含了读写锁。尽管如此,我们还是应该了解其实现背后的原理。

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {

    static Map map = new HashMap();
    static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    static Lock r = rwl.readLock();
    static Lock w = rwl.writeLock();

    // 获取一个key对应的value
    public static final Object get(String key) {
        r.lock();
        try {
            System.out.println("正在做读的操作,key:" + key + " 开始");
            Thread.sleep(100);
            Object object = map.get(key);
            System.out.println("正在做读的操作,key:" + key + " 结束");
            System.out.println();
            return object;
        } catch (InterruptedException e) {

        } finally {
            r.unlock();
        }
        return key;
    }

    // 设置key对应的value,并返回旧有的value
    public static final Object put(String key, Object value) {
        w.lock();
        try {

            System.out.println("正在做写的操作,key:" + key + ",value:" + value + "开始.");
            Thread.sleep(100);
            Object object = map.put(key, value);
            System.out.println("正在做写的操作,key:" + key + ",value:" + value + "结束.");
            System.out.println();
            return object;
        } catch (InterruptedException e) {

        } finally {
            w.unlock();
        }
        return value;
    }

    // 清空所有的内容
    public static final void clear() {
        w.lock();
        try {
            map.clear();
        } finally {
            w.unlock();
        }
    }

    public static void main(String[] args) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i             
关注
打赏
1688896170
查看更多评论
0.3246s