5、线程同步(保证资源合理共享)
线程安全问题:多线程环境中操作共享资源,由于多个线程争抢CPU执行权具有随机性,所以会出现资源调度混乱的情况 。
线程同步:可以形象的理解为给共享资源配一把“锁”,每次只有一个线程可以访问 ,从而防止资源访问的冲突 。
Java提供同步块来实现线程同步:
public class ThreadTwo implements Runnable{
private int num=10;
//创建“锁”对象
private Object mutex=new Object();
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
//进入同步代码块之前,三个线程都在争抢
/**
* 同步块
*/
synchronized (mutex) {
//进来之后只要一个线程行代码块
if(num>0){
try {
Thread.sleep(1000);//当前线程睡眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+num--);
}
}
}
}
}
也可以用同步方法来实现线程同步:
public class ThreadTwo implements Runnable{
private int num=10;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
//进同步代码块之前,三者都在抢
sale();
}
}
/**
* 同步方法
*/
public synchronized void sale(){
if(num>0){
try {
Thread.sleep(1000);//当前线程睡眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+num--);
}
}
}
创建线程并启动:
public class ThreadTwoMain {
public static void main(String[] args) {
//创建接口对象
Runnable r=new ThreadTwo();
//根据接口对象创建线程对象
Thread t1=new Thread(r, "林志玲");
Thread t2=new Thread(r, "林心如");
Thread t3=new Thread(r, "蔡依林");
t1.start();
t2.start();
t3.start();
}
}
线程同步之前,输出:
林志玲:10
林志玲:9
林志玲:8
林志玲:7
林志玲:6
林心如:5
林心如:4
蔡依林:3
林心如:2
林心如:1
林心如:0
林心如:-1
线程同步之后:
林志玲:10
林志玲:9
林志玲:8
林志玲:7
林志玲:6
林心如:5
林心如:4
蔡依林:3
林心如:2
林心如:1
线程同步之前,当num=1时,三个线程先后获取到了CPU的执行权,
线程1执行num--,输出1,num再减1;
线程2执行num--,输出0,num再减1;
线程3执行num--,输出-1,num再减1;
所以会出现0,-1 。
线程同步之后,只有一个线程能够执行共享代码,所以输出正常 。
6、死锁
当两个或多个线程之间同时等待对方释放资源,就会形成线程之间的死锁。
同步嵌套会导致死锁,可以形象地理解为,线程A需要线程B的“锁”才能继续执行,同样,线程B也需要线程A的“锁”才能继续执行,二者“僵持”,形成死锁 。
代码示例:
//定义两把锁
public class MyLock {
public static Object objA=new Object();
public static Object objB=new Object();
}
//死锁代码
public class DieLock implements Runnable{
private boolean flag;
public DieLock(boolean flag){
this.flag=flag;
}
@Override
public void run() {
if(flag){
//A获取自己的锁
synchronized (MyLock.objA) {
System.out.println("objA First!");
//A要获取B的锁,但是B在用
synchronized (MyLock.objB) {
System.out.println("objB Second!");
}
}
}else{
//B获取自己的锁
synchronized (MyLock.objB) {
System.out.println("objB First!");
//B要获取A的锁,但是A在用
synchronized (MyLock.objA) {
System.out.println("objA Second!");
}
}
}
}
}
//创建线程并启动
public class DieLockMain {
public static void main(String[] args) {
Thread A=new Thread(new DieLock(true));
Thread B=new Thread(new DieLock(false));
A.start();
B.start();
}
}
输出:
objA First!
objB First!