java 多线程随笔(二)

继续上一篇文章,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. 信号量 指定多个线程访问一个资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值