临界区:临界区是一个用以访问访问共享资源的代码块,这个代码块在同一时间内只允许一个线程执行。
重入锁:当末个线程请求一个由其他线程持有的锁时,发出的请求的线程就会阻塞,然而内置锁(synchronized)是可重入的,因此如果末个线程试图获得一个已经由他自己持有的锁,那么这个请求就会成功。
synchronized 和 ReentrantLock 都是重入锁。
public class Test1 {
private static Object lock = new Object();
private int i;
public Test1(int i) {
super();
this.i = i;
}
public void getone()throws Exception{
Thread.sleep(i*1000);
synchronized (lock) {
System.out.println("获取第二个锁");
}
}
public void gettwo()throws Exception{
Thread.sleep(i*1000);
synchronized (lock) {
System.out.println("获取第一个锁");
getone();
}
}
public static void main(String[] args) throws Exception{
for(int i=1;i<4;i++){
final Test1 test1 = new Test1(i);
new Thread(new Runnable() {
@Override
public void run() {
try {
test1.gettwo();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();;
}
}
}
输出结果:
获取第一个锁
获取第二个锁
获取第一个锁
获取第二个锁
获取第一个锁
如果getone()方法 不能获取lock锁的对象,那么gettwo()这个方法就会一直阻塞,整个线程都会阻塞。
public class Test1 {
private static ReentrantLock lock = new ReentrantLock();
private int i;
public Test1(int i) {
super();
this.i = i;
}
public void getone()throws Exception{
Thread.sleep(i*1000);
lock.lock();
System.out.println("获取第二个锁");
lock.unlock();
}
public void gettwo()throws Exception{
Thread.sleep(i*1000);
lock.lock();
System.out.println("获取第一个锁");
getone();
lock.unlock();
}
public static void main(String[] args) throws Exception{
for(int i=1;i<4;i++){
final Test1 test1 = new Test1(i);
new Thread(new Runnable() {
@Override
public void run() {
try {
test1.gettwo();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();;
}
}
}
输出结果:
获取第一个锁
获取第二个锁
获取第一个锁
获取第二个锁
获取第一个锁
获取第二个锁
lock 获取几次锁就要释放几次,不然线程就会阻塞。
lock获取锁的代码:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果获取不到锁,进判断当前线程和持有锁的线程是否是同一个
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
synchronized:如果写在方法上 那么锁住的是当前对象是this,如果写在静态方法上那么锁住就是当前类的Class如:XX.Class。
ReentrantLock: lock.tryLock() 尝试获取锁,如果获取到就true, 获取不到就返回,这样线程获取不到锁线程也不会阻塞。