在循环中synchronized包裹循环体后为什么不会释放锁?
问题描述:
小白刚学到线程加锁,然后发现在while循环中只要整个循环体都被同步代码块包含的话就只要满足条件线程获得锁后不会释放锁,尝试了一下在同步代码块外随便加一个都可以释放锁,所以想问一下while循环中判断的时候为什么不会释放锁?
我的理解是Synochronized代码块结束之后,释放锁,执行while判断,双线程争夺锁。 可是不知道为什么直接就跳过了释放的过程。。。
public class TickerPoolTest {
public static void main(String[] args) {
Pool1 p = new Pool1();
Saler1 s1 = new Saler1(1,p);
Saler1 s2 = new Saler1(2,p);
new Thread(s1).start();
new Thread(s2).start();
}
}
class Pool1{
static int size = 20;
}
class Saler1 implements Runnable{
private int num;
private Pool1 pool;
private int sale = 0;
public Saler1(int num, Pool1 pool) {
super();
this.num = num;
this.pool = pool;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public void run() {
for(int i = 0;i<20;i++){
synchronized(pool){
pool.size--;
System.out.println("出票员"+num +"卖出一张,余票"+ pool.size);
if(pool.size == 0)
System.exit(0);
}
//这里是我后来加的,使用了一行空输出来达到释放锁的效果
System.out.print("");
}
}
}
更新:
因为样本过小导致线程交替没显示,结帖
答
我的理解是:
线程并发执行,是通过cpu时间片轮转执行的,当你时间片执行完,线程1还占用着锁,线程2就会等待不会执行,然后线程1继续执行下一个时间片;
如果时间片执行完,线程1是没有占用锁,线程2才能执行;你在同步代码外面加了一句输出语句,只不过加大了时间片执行完线程是进行到同步代码块外的可能;
你可以试试去掉那句输出,也可能另一个线程也执行得到。
答
你说的跳过是指什么
答
从你这段代码来看,每一轮循环的的还是都会先尝试获取锁,执行完成后释放继续下一轮,这样两个线程可能是交替获取锁或者一个线程抢占锁的。
你加的信息应该体现线程名称类似这样:
System.out.println(Thread.currentThread().getName()+new Date());