Java线程的同步--线程安全的原因及解决方法

线程的同步

如果线程不同步,会发生两个线程抢占资源的问题;例如火车票出售时,只有最后一张票,但两个人一起买就会出现系统问题。所以为了避免资源抢占的问题,在使用线程的同步时应该考虑线程的安全

1.不安全的线程:
同一进程下不同的线程是共享系统资源的,资源好比一个独木桥,如果两个线程,同时过独木桥的话就会发生不安全的情况(资源的抢用会造成:脏数据,死锁等问题)

2.安全的线程
过独木桥时,一个先给出指令先过桥,过完后再次发出指令,已经完成过桥
要保证线程的安全:需要给线程加锁:
加锁—’过桥‘—解锁

加锁:synchronized关键字
同步方法:synchronized void method(){
}
同步代码块 synchronized(Object){

} Object:任意对象,仅作为加锁的标志

首先举一个不安全的线程同步例子:

//模拟售票系统
public class 同步 implements Runnable{
    int num = 10;//票池的总数
	public static void main(String[] args) {
		同步 d =new 同步();
		Thread t1= new Thread(d,"线程1");//售票机1
		Thread t2= new Thread(d,"线程2");//售票机2
		Thread t3= new Thread(d,"线程3");//售票机3
		Thread t4= new Thread(d,"线程4");//售票机4
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
	public void run() {
		while(true) {
			if(num>0) 
				try {
					Thread.sleep(100);//休眠100毫秒
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("票数:"+num);
				num--;
				if(num<0) {
					break;
				}
			}
		}
		
	}

结果如下:
票数:10
票数:7
票数:8
票数:9
票数:6
票数:3
票数:4
票数:5
票数:2
票数:1
票数:0
票数:-1
票数:-2
票数:-3

采用同步代码块的方法使线程安全:

//模拟售票系统
public class 同步 implements Runnable{
    int num = 10;//票池的总数
	public static void main(String[] args) {
		同步 d =new 同步();
		Thread t1= new Thread(d,"线程1");//售票机1
		Thread t2= new Thread(d,"线程2");//售票机2
		Thread t3= new Thread(d,"线程3");//售票机3
		Thread t4= new Thread(d,"线程4");//售票机4
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
	public void run() {
		while(true) {
			synchronized (this) {//同步代码块,所以线程同步此代码块
				if(num>0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					System.out.println("票数:"+num);
					num--;
					if(num<0) {
						System.out.println("已售空");
						break;
					}
				}
			}
		}
	}
		
}

采用同步方法的解决方法

//模拟售票系统
public class 同步 implements Runnable{
    int num = 10;//票池的总数
	public static void main(String[] args) {
		同步 d =new 同步();
		Thread t1= new Thread(d,"线程1");//售票机1
		Thread t2= new Thread(d,"线程2");//售票机2
		Thread t3= new Thread(d,"线程3");//售票机3
		Thread t4= new Thread(d,"线程4");//售票机4
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
	private synchronized void sell() {//线程同步的方法
		if(num>0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			System.out.println("票数:"+num);
			num--;
			if(num<0) {
				System.out.println("已售空");
			}
		}
	}
	public void run() {
		while(true) {
			sell();
			}
	}
		
}
发布了20 篇原创文章 · 获赞 13 · 访问量 1988

猜你喜欢

转载自blog.csdn.net/qq_42724864/article/details/104506135
今日推荐