为了解决线程安全问题,控制各子线程对临界资源的访问,可以使用lock方法,在要访问临界资源的代码前加锁,在访问后解锁,即可。大部分时候需要结合循环+判断语句进行代码的编写,需要注意的是,尽量使用while(true)+if(参数判断),尽量不要使用whle(参数判断)。
详见以下两种代码,注意如果结果不尽人意可以增加票数和睡眠时间:
第一种:while(true)+if(参数判断)
package myfirst_Java;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//import jdk.nashorn.api.tree.NewTree;
/**
* @author 17621802479
*
*/
class Sellticket implements Runnable{
private int ticket=10;
Object ob =new Object();
Lock lock1=new ReentrantLock();
@Override
public void run() {
//特别注意这里的循环+判断方式和加锁的位置,原则上加锁和解锁内的代码包含临界资源就可以了,这里的临界资源就是ticket,
//因此只要有关ticket的代码前后加锁和解锁就行了,为了代码好看,我这里在判断前加锁,在else后解锁,其实测试了,可以在ticket--后解锁的。
while(true) {
lock1.lock();
if(ticket>0) {
try {
Thread.sleep(50);
System.out.println(Thread.currentThread().getName()+"正在卖"+ticket+"张票");
ticket--;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
//这里一定要有解锁,否则退出循环时还没有解锁,会造成有线程卡在循环内。
//例如假设线程2刚好运行完while(true),但是上一个线程运行完之后没有解锁,即使已经没票了,线程2是无法通过访问else退出循环的。
lock1.unlock();
break;
}
lock1.unlock();
}
}
}
public class Hello {
public static void main(String[] args) {
Sellticket Sell=new Sellticket();
Thread t1=new Thread(Sell,"线程1");
Thread t2=new Thread(Sell,"线程2");
Thread t3=new Thread(Sell,"线程3");
t1.start();
t2.start();
t3.start();
}
}
结果正确
第二种:while(参数判断)
package myfirst_Java;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Sellticket implements Runnable{
private int ticket=10;
Lock lock1=new ReentrantLock();
//这里用while(ticket>0)方法,最后结果就是只有一个线程,因为一旦有线程获得cpu控制权,就会一直循环执行,直到没票,
//这样其他线程根本没有机会进入循环执行操作。
@Override
public void run() {
lock1.lock();
while(ticket>0) {
try {
Thread.sleep(50);
System.out.println(Thread.currentThread().getName()+"正在卖"+ticket+"张票");
ticket--;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
lock1.unlock();
}
}
public class Hello {
public static void main(String[] args) {
Sellticket Sell=new Sellticket();
Thread t1=new Thread(Sell,"线程1");
Thread t2=new Thread(Sell,"线程2");
Thread t3=new Thread(Sell,"线程3");
t1.start();
t2.start();
t3.start();
}
}
结果错误,只有一个线程执行。