java多线程学习笔记(三)

一、线程简介

请看:https://blog.csdn.net/qq_33157666/article/details/103949005

二、线程状态

请看:https://blog.csdn.net/qq_33157666/article/details/103949045

三、线程同步

 为什么要进行线程同步?

 java允许多线程并发控制,当多个线程同时操作一个可共享资源变量时(如对其进行增删改查操作),会导致数据不准确,而且相互之间产生冲突。所以加入同步锁以避免该线程在没有完成操作前被其他线程调用,从而保证该变量的唯一性和准确性。

3.1初识并发问题

//多个线程同时操作同一个对象
//买火车票的例子

//发现问题:多个线程操作同一个资源的情况下,线程不安全,数据混乱
public class TestTheard4 implements Runnable{
	//票数
	private int ticketNumbers=10;

	@Override
	public void run() {
		while(true){
			if(ticketNumbers<=0){
				break;
			}
			System.out.println(Thread.currentThread().getName()+"--->拿到了"+ticketNumbers--+"票");
		}
	}
	

	public static void main(String[] args) {
		TestTheard4 testTheard4=new TestTheard4();
		new Thread(testTheard4,"小明").start();
		new Thread(testTheard4,"小张").start();
		new Thread(testTheard4,"黄牛党").start();
		
	}
}

java多线程学习笔记(三)_第1张图片

可以看到小明和小张同时拿到了第9张票,这样线程是不安全的,需要做到同步,可以把同步理解成排队,不让多个线程操作同一个对象。可使用synchronized关键字实现同步。

引起线程不安全的原因:

每个线程的内存都是独立的,当两个线程同时访问一个对象时,会把对象复制到自己内存中,所以,如果想线程安全需要排队。

3.2 同步方法

同步方法:用synchronize关键字修饰的方法,当用synchronize关键字修饰方法时,一个线程持有锁后将其他需要此锁的线程挂起。

   代码修改:将4.1代码的run方法改为:

@Override
	public synchronized void run() {

3.3同步代码块

同步代码块:就是拥有synchronize关键字修饰的语句块

代码修改:将4.1代码的

@Override
	public void run() {
		while(true){
			synchronized (this) {
			if(ticketNumbers<=0){
				break;
			}
			System.out.println(Thread.currentThread().getName()+"--->拿到了第"+ticketNumbers--+"票");
			}
		}
	}

3.4小结

synchrionized实现同步的原理:

synchronized方法控制对象访问,每个对象对应一个把锁,每个synchized方法必须获得调用对象该对象的锁才能执行,否则会线程阻塞,方法一旦执行,就独占改锁,知道该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,持续执行。

使用synchronized的缺点:

  • 一个线程持有所会导致其他需要此锁的线程挂起,在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
  • 如果有一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题。

四、死锁

请看:https://blog.csdn.net/qq_33157666/article/details/103949174

你可能感兴趣的:(java基础)