可重入锁
package TCPUDPThread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 可重入锁
* 锁作为并发共享数据保证一致性的工具,大多数内置锁都是可重入的,也就是说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立刻成功,并且将这个锁的计数值加1,而当线程退出同步代码块时,计数器将会递减,当计数值等于0时,锁释放.
* 如果没有可重入锁的支持,在第二次企图获得锁时将会进入死锁状态.可重入锁随处可见
*
* 可重入锁,锁可以延续使用
*/
/**
* 可重入锁演示
* @author pmc
*
*/
public class synchronizedTest16 {
public synchronized void a(){
System.out.println("a()");
}
public synchronized void b(){
System.out.println("b()");
}
/**
* 可重入锁用法
*/
public synchronized void all(){
a();
b();
}
public static void main(String[] args) {
new Thread(()->{
//第一次获得锁
synchronized(synchronizedTest16.class){
while(true){
System.out.println("1");
//第二次获得同样的锁
synchronized(synchronizedTest16.class){
System.out.println("2");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
synchronizedTest16 t6=new synchronizedTest16();
t6.all();
}
}
不可重入改可重入/ReentrantLock
package TCPUDPThread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 可重入锁
* 锁作为并发共享数据保证一致性的工具,大多数内置锁都是可重入的,也就是说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立刻成功,并且将这个锁的计数值加1,而当线程退出同步代码块时,计数器将会递减,当计数值等于0时,锁释放.
* 如果没有可重入锁的支持,在第二次企图获得锁时将会进入死锁状态.可重入锁随处可见
*
* 可重入锁,锁可以延续使用
*/
/**
* 可重入锁演示
* @author pmc
*
*/
public class synchronizedTest15 {
//ReentrantLock lock=new ReentrantLock();
ReLock lock=new ReLock();
public void a() throws Exception{
lock.lock();
b();
lock.unlock();
}
public void b() throws Exception{
lock.lock();
System.out.println("B");
lock.unlock();
}
public static void main(String[] args) throws Exception {
synchronizedTest15 test=new synchronizedTest15();
test.a();
}
}
/**
*//**改为重入锁代码
* @author pmc
*
*/
class ReLock{
//是否占用
private boolean isLockde=false;
Thread locked=null;//存储线程**
private int count=0;//**
//使用锁
public synchronized void lock() throws Exception{
Thread t=Thread.currentThread();//**
while(isLockde&&locked!=t){//**
System.out.println(isLockde);
System.out.println("1");
wait();
System.out.println("2");
}
isLockde=true;
locked=t;//**
count++;//**
}
//释放锁
public synchronized void unlock(){
if(Thread.currentThread()==locked){//**
count--;//**
if(count==0){//**
isLockde=false;
notify();
locked=null;
}
}
}
}
ReentrantLock常常对比着synchronized
(1)synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。
(2)synchronized可重入,因为加锁和解锁自动进行,不必担心最后是否释放锁;ReentrantLock也可重入,但加锁和解锁需要手动进行,且次数需一样,否则其他线程无法获得锁。
(3)synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以相应中断。
ReentrantLock好像比synchronized关键字没好太多,我们再去看看synchronized所没有的,一个最主要的就是ReentrantLock还可以实现公平锁机制。什么叫公平锁呢?也就是在锁上等待时间最长的线程将获得锁的使用权。通俗的理解就是谁排队时间最长谁先执行获取锁。