Discuss / Java / ReentrantLock 样例code

ReentrantLock 样例code

Topic source

Junes_99994

#1 Created at ... [Delete] [Delete and Lock User]

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

import java.util.concurrent.TimeUnit;

public class ReentrantLockTest {

    public static void main(String[] args) {

        // same Resource and Lock

        Resource r = new Resource();

        final Lock lock = new ReentrantLock();

        for (int i = 1; i < 5; i++) {

            // final int c = i;

            Thread t = new Thread(new ConcurrencyLockExample(r, lock, i));

            t.start();

        }

    }

}

class Resource {

    private int m = 0;

    public void doSomething(int n) {

        // do some operation, DB read, write etc

        m += n;

        try {

            Thread.sleep(200);

        } catch (InterruptedException e) {

        }

    }

    public void doLogging() {

        // logging, no need for thread safety

    }

    public int getM() {

        return m;

    }

}

class ConcurrencyLockExample implements Runnable {

    private Resource resource;

    private Lock lock;

    private String tN;

    public ConcurrencyLockExample(Resource r, Lock lock, int tN) {

        this.resource = r;

        this.tN = "Thread_" + tN;

        this.lock = lock;

    }

    @Override

    public void run() {

        try {

            System.out.println(tN + " try to get Resource");

            if (lock.tryLock(1, TimeUnit.SECONDS)) {

                System.out.println(tN + " GoT Resource");

                resource.doSomething(10);

                System.out.println(tN + " Processed Resource: " + resource.getM());

            }

        } catch (InterruptedException e) {

            e.printStackTrace();

        } finally {

            // release lock

            System.out.println(tN + " releasing Resource");

            lock.unlock();

            System.out.println(tN + " released Resource");

        }

        resource.doLogging();

    }

}

Junes_99994

#2 Created at ... [Delete] [Delete and Lock User]

程序有问题

如果tryLock 1s内没有获取到资源,之后lock.unlock() 会有无锁可解的错误

所以在解锁前可作判断 lock.islocked()  或者 将 lock.unlock() 嵌入tryLock判断之内,

但不知为何,我的ReentrantLock 中没有 islocked 方法,那只能先手动设置标志位了

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html

Junes_99994

#3 Created at ... [Delete] [Delete and Lock User]

原来是 lock 类型错误 ,应该定义为 ReentrantLock 而不是 Lock

但这样还是有错误,当把doSomething的延时时间调整为 1500

单纯通过 lock.isLocked() 判断解锁,会错误的对其他正在占用该锁的线程解锁

Junes_99994

#4 Created at ... [Delete] [Delete and Lock User]

使用 lock.isHeldByCurrentThread() 可以确认是否是当前线程占用此lock,

这样配合 lock.isLocked()  就能判断是否需要解锁

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

// import java.util.concurrent.locks.*;

import java.util.concurrent.TimeUnit;

public class ReentrantLockTest {

    public static void main(String[] args) {

        // same Resource and Lock

        Resource r = new Resource();

        final ReentrantLock lock = new ReentrantLock();

        for (int i = 1; i < 5; i++) {

            // final int c = i;

            Thread t = new Thread(new ConcurrencyLockExample(r, lock, i));

            t.start();

        }

    }

}

class Resource {

    private int m = 0;

    public void doSomething(int n) {

        // do some operation, DB read, write etc

        m += n;

        try {

            Thread.sleep(1500);

        } catch (InterruptedException e) {

        }

    }

    public void doLogging() {

        // logging, no need for thread safety

    }

    public int getM() {

        return m;

    }

}

class ConcurrencyLockExample implements Runnable {

    private Resource resource;

    private ReentrantLock lock;

    private String tN;

    private boolean taskToDo = true;

    public ConcurrencyLockExample(Resource r, ReentrantLock lock, int tN) {

        this.resource = r;

        this.tN = "Thread_" + tN;

        this.lock = lock;

    }

    @Override

    public void run() {

        while (taskToDo) {

            try {

                System.out.println(tN + " try to get Resource");

                if (lock.tryLock() || lock.tryLock(1, TimeUnit.SECONDS)) {

                    System.out.println(tN + " GoT Resource");

                    resource.doSomething(10);

                    System.out.println(tN + " Processed Resource: " + resource.getM());

                    taskToDo = false;

                }

            } catch (InterruptedException e) {

                e.printStackTrace();

            } finally {

                // release lock

                if (lock.isHeldByCurrentThread() && lock.isLocked()) {

                    System.out.println(tN + " releasing Resource");

                    lock.unlock();

                    System.out.println(tN + " released Resource");

                }

            }

        }

        resource.doLogging();

    }

}

Junes_99994

#5 Created at ... [Delete] [Delete and Lock User]

lock.isHeldByCurrentThread() 包含了 lock.isLocked() 的情况

回复“如果tryLock 1s内没有获取到资源,之后lock.unlock() 会有无锁可解的错误”。没有获取到锁就别unlock了呀。你看老师的unlock代码也是写在tryLock成功里面的呀。


  • 1

Reply