临界资源问题
先看例子
public class SourceConflict {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (TicketCenter.currnetTicket > 0) {
System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
}
}
};
Thread t1 = new Thread(runnable, "t1");
Thread t2 = new Thread(runnable, "t2");
Thread t3 = new Thread(runnable, "t3");
Thread t4 = new Thread(runnable, "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TicketCenter{
public static int currnetTicket = 100;
}
运行程序,四个线程共享ticket资源,会同时操作票资源,不做处理会出现下面的问题
解决方法一:同步代码段
public class SynchronizedDemo {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (TicketCenter.currnetTicket > 0) {
//对象锁
synchronized ("") {
System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
}
}
}
};
Thread t1 = new Thread(runnable, "t1");
Thread t2 = new Thread(runnable, "t2");
Thread t3 = new Thread(runnable, "t3");
Thread t4 = new Thread(runnable, "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
上面的 //对象锁 synchronized ("") 可替换成
//类锁 synchronized(SynchronizedDemo.class)
只要保证四个线程看到的是同一所即可,
synchronized(new SynchronizedDemo())会报错,因为每次都会生成不同对象
好接下来我们看运行代码结果(我们的结果不一定相同)
但是!!!!!!!!
这是因为t2卖票时,t1,t3,t4拿到资源在锁外等待,线程切换的时候,他们看到的票数还是>0的,当t2卖出最后一张,票数为0,t1,t3,t4再做卖票动作时,会产生负数。
修改成这样就好了
synchronized ("") {
if (TicketCenter.currnetTicket == 0) {
return;
}
System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
}
解决方法二:同步方法
public class SynchronizedFunction {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (TicketCenter.currnetTicket > 0) {
sell();
}
}
};
Thread t1 = new Thread(runnable, "t1");
Thread t2 = new Thread(runnable, "t2");
Thread t3 = new Thread(runnable, "t3");
Thread t4 = new Thread(runnable, "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
/*同步方法
静态方法:同步锁就是类锁, 当前类.class
非静态方法: 同步锁是 this*/
public synchronized static void sell(){
if (TicketCenter.currnetTicket == 0) {
return;
}
System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
}
}
看结果
当需要同步的逻辑比较复杂的时候可以将他们放在方法里
解决方法三:显示锁
public class LockDemo {
public static void main(String[] args) {
final ReentrantLock lock = new ReentrantLock();
Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (TicketCenter.currnetTicket > 0) {
//对临界资源加上显示锁
lock.lock();
if (TicketCenter.currnetTicket <= 0) {
return;
}
System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
//对临界资源释放锁
lock.unlock();
}
}
};
Thread t1 = new Thread(runnable, "t1");
Thread t2 = new Thread(runnable, "t2");
Thread t3 = new Thread(runnable, "t3");
Thread t4 = new Thread(runnable, "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
结果没有问题,但是。。。
运行之后程序没有停止,有大佬可以告诉我为什么吗?