java 多线程随笔(二)

来源:互联网 发布:读书笔记软件下载 编辑:程序博客网 时间:2024/06/05 14:55

继续上一篇文章,synchronized 的功能扩展,重入锁。

  1. ReenterLock 重入锁
    为什么叫重入锁呢?因为锁是可以反复进入的,针对一个线程来说的
    与synchronized 比较写一下
    第一 ReenterLock 需要手动释放锁,synchronized 不需要
    第二 中断响应 对于synchronized 如果一个线程在等待,只有继续执行或等待,但是重入锁可以等待时,进行中断。
    reentrantLock.lockInterruptibly();//获得锁,优先中断
    第三 限时等待锁
    tryLock有二个参数 第一个是等待时长 第二个是单位
    例子 tryLock等待5秒 Thread获取锁6秒,所以例子请求锁失败。
mport java.util.concurrent.TimeUnit;import java.util.concurrent.locks.ReentrantLock;public class TryLockTest implements Runnable{    private static ReentrantLock lock=new ReentrantLock();    @Override    public void run() {        try {            if(lock.tryLock(5, TimeUnit.SECONDS)) {                Thread.sleep(6000);            }else {                System.out.println("get lock failed");            }        }catch (Exception e){            e.printStackTrace();        }finally {            if(lock.isHeldByCurrentThread()){                lock.unlock();            }        }    }    public static void main(String args[]){        TryLockTest test=new TryLockTest();        Thread thread1=new Thread(test);        Thread thread2=new Thread(test);        thread1.start();        thread2.start();    }}

第四 公平锁 例子

import java.util.concurrent.locks.ReentrantLock;/**o 1. 重入锁 与synchronized */public class RelockTest implements Runnable{    private static ReentrantLock reentrantLock=new ReentrantLock(true);//公平锁    @Override    public void run() {        while (true) {            try {            reentrantLock.lockInterruptibly();//获得锁,优先中断                //reentrantLock.lock();                System.out.println(Thread.currentThread().getId()+"获得锁");            } catch (InterruptedException e) {            } finally {                reentrantLock.unlock();            }        }    }    public static void main(String args[]){        RelockTest relockTest= new RelockTest();        Thread thread1=new Thread(relockTest, "tr1");        Thread thread2=new Thread(relockTest, "tr2");        thread1.start();        thread2.start();    }}

就是两个线程可以公平的获取线程
2. Condition 条件

signal
void signal()唤醒一个等待线程。
如果所有的线程都在等待此条件,则选择其中的一个唤醒。在从 await 返回之前,该线程必须重新获取锁定。
上个例子:

作为一个示例,假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put 操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put 线程和 take 线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个 Condition 实例来做到这一点。

 class BoundedBuffer {   final Lock lock = new ReentrantLock();   final Condition notFull  = lock.newCondition();    final Condition notEmpty = lock.newCondition();    final Object[] items = new Object[100];   int putptr, takeptr, count;   public void put(Object x) throws InterruptedException {     lock.lock();     try {       while (count == items.length)          notFull.await();       items[putptr] = x;        if (++putptr == items.length) putptr = 0;       ++count;       notEmpty.signal();     } finally {       lock.unlock();     }   }   public Object take() throws InterruptedException {     lock.lock();     try {       while (count == 0)          notEmpty.await();       Object x = items[takeptr];        if (++takeptr == items.length) takeptr = 0;       --count;       notFull.signal();       return x;     } finally {       lock.unlock();     }   }  }

(ArrayBlockingQueue 类提供了这项功能,因此没有理由去实现这个示例类。)
3. 信号量 指定多个线程访问一个资源

原创粉丝点击