java-锁

一  java-锁 目的 

    目的:防止多线程执行某段代码时导致的数据异常,互相干扰,所以把某段代码块加上锁,保证其原子性

二    使用  synchronized   (java语言内置锁)

    2.11 单独使用于对象,使用对象锁
object object_lock = new object();

public void run()

{

     //被锁住的代码块,保证了原子性,同一时间只能被一个线程所操作
    synchronized(object_lock){
       do something;
    }

}

Java中的每个对象都有一个监视器,来监测并发代码的重入,上面就synchronized获取了lock的监视器,

    2.2  synchronized 用于方法,

public class Thread1 implements Runable{

public synchronized void run()
{
do something
}

}

其实是获取了Thread1的监视器,对象锁。

线程同步方法是通过锁来实现,每个对象都有且仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,
其他访问该对象的线程就无法再访问该对象的其他同步方法。

三   java 显示锁

2.1 第一种显示锁  Lock

是语法层级的锁,
常用方法有
//获取锁
lock();
//释放锁
unlock();
//尝试获取锁
trylock();

Lock的实现为ReentrantLock()

使用范式为

//显示锁
Lock lock = new ReentrantLock();
//获取锁
lock.lock();
try {
//执行业务

} finally {
//释放锁
lock.unlock();
}

获取锁之后,一定要在finally中释放掉,

Lock与synchronized的比较

1 synchronized 代码简洁
2 Lock获取锁可以被中断,可以设置超时,可以尝试获取锁

如果业务场景满足2中这3点,可以考虑用Lock,否则就用synchronized。

2.2 第2种显示锁  读写锁 ReadWriteLock 接口

实现为 ReentrantReadWriteLock

    概念:同一时刻允许多个线程同时访问,但是写线程访问的时候,所有线程都被阻塞
最适用于读多写少情况,比普通线程性能几何倍增加

用法


//读写锁对象
ReadWriteLock myLock = new ReentrantReadWriteLock();
//读锁
Lock readLock = myLock.readLock();
//写锁
Lock writeLock = myLock.writeLock();

然后在多线程中,读的地方用读锁,写的地方用写锁即可。

2.3 Lock 里面的等待和通知

实现:

Lock lock = new ReentrantReadWriteLock();
Condition kmCondition = lock.newCondition();

kmCondition.await();//等待
kmCondition.signal();//通知

三  名次解释

3.1 可重入锁

就是可以被多次获取的锁


public synchronized void testA()
{
System.out.println("A方法执行业务");
testB();
}

public synchronized void testB()
{
System.out.println("B方法执行业务");
}

testA本身有一把锁,调用了testB()又一把锁,共2把锁,即多次获取了锁,叫重入锁。

public void lockTest() {
//获取锁
lock.lock();
try {
System.out.println("第一次获取了锁");
lock.lock();
try {
System.out.println("第二次获取了锁");
} finally {
//释放锁
lock.unlock();
}
} finally {
//释放锁
lock.unlock();
}
}

上面例子里,lock也可以获取2次锁,lock也是可重入锁

由此可见,synchronized  和Lock都属于可重入锁

3.2 公平锁和非公平锁

      公平锁的概念:如果在时间上,先对锁进行获取的请求一定先被满足,这个锁就是公平锁(即先等先得),反之为非公平锁(随机给锁)
一般是Lock构造器默认的非公平锁,如果需要公平锁也可指定。

效率对比
非公平锁效率更高,为什么? 请看下面解释

时刻1  A线程 获取到了锁 
时刻2  B线程此时也来请求拿锁 被阻塞,被操作系统挂起
时刻3  A线程执行完业务,释放了锁
时刻3  C线程也来请求锁

非公平锁工作机制
    此时计算机把锁给C而不是给B


公平锁工作机制
    此时计算机把锁给B而不是给A
但是此时B是挂起状态,所以首先要把线程B从挂起状态恢复为正常状态(这个过程会耗费较长的时间)

     用非公平锁,把锁给C以后,C执行完业务后,可能刚好B从挂起状态恢复为正常(有这个概率),相对公平锁来说,就有机会减少唤醒挂起线程的这段时间,
所以我们说非公平说效率更高。

当然具体用哪种要根据业务,比如某些优先级高的业务,就想要优先执行,也可以用公平锁。

猜你喜欢

转载自www.cnblogs.com/hup666/p/11886158.html
今日推荐