多线程的学习心得

1.synchronized的三种应用方式
<1>修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁

<2>修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁

<3>修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

synchronized修饰实例方法:

public synchronized void produceApple(Apple apple) {
		while(index>=apples.length) {
			//容器已满,无法继续生产苹果
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		this.notifyAll();
		//生产苹果
	
		apples[index] =apple;
		System.out.println(Thread.currentThread().getName()+"生产了编号为:"+apple.id+"的苹果");
		index++;
	}

	//取苹果
public synchronized Apple eatApple() {
	while(index<=0) {
		//苹果全部消费,等待生产者生产
		try {
			this.wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	this.notifyAll();
	//消费苹果
	index--;
	System.out.println(Thread.currentThread().getName()+"消费编号为:"+apples[index].id+"的苹果");
	return apples[index];
}	

修饰代码块方法:

public void run() {
		// TODO Auto-generated method stub
		if(flag) {
			synchronized (zs) {
				zs.say();
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			
			//同时 锁住 lisi
		synchronized (ls) {
				zs.get();
				
			}	
			}
		}

synchronized的一些作用域:

1.synchronized修饰实例方法时,多个线程同时访问该类的的实例方法,只有一个线程可以获得锁,也就算该类所有被synchronized修饰的方法只能被同一个线程访问(获得锁的线程),其他线程只能访问没有被synchronized修饰的方法,但是如果synchronized修饰静态方法当前类就是锁对象,所以该类的实例方法即使被synchronized修饰也是能被其他线程访问的

2.得到对象锁的线程可以访问该对象中其他被synchronized修饰的方法;

3.子类的synchronized方法中可以调用父类的synchronized方法;

volatile关键字:

public class Test02 {
    private  boolean flag=true;
    public  void m(){
        System.out.println("start");
      while(flag){

      }
        System.out.println("end");
    }

    public static void main(String[] args) {
        Test02 t2=new Test02();
    new Thread(()->t2.m()).start();
        try {
            Thread.sleep(1000);//rangcpu空闲下来区读取数据存入缓存
        } catch (Exception e) {
            e.printStackTrace();
        }
        t2.flag=false;
    }
}

结果:
start

将flag变量加上volatile后

start
end

不加volatile关键字,cpu将线程中的flag读取到自己的缓存中后,即使cpu调度其他线程来改变了它,他也不会重新将修改了的值读取到缓存,加上volatile关键字后,若值改变,就会通知cpu重新读取缓存中修改后的值
在这里插入图片描述

wait()会释放锁,notify不会释放锁;

在这里插入图片描述
在这里插入图片描述

发布了23 篇原创文章 · 获赞 8 · 访问量 1400

猜你喜欢

转载自blog.csdn.net/lin1214000999/article/details/99693882
今日推荐