线程间通信的方式----全面解析

并发编程核心技术
本文深入解析了volatile和synchronize在并发编程中的作用,包括数据的可见性、原子性和有序性;详细介绍了等待通知机制的实现原理及其在多线程环境下的应用;探讨了管道输入输出流的绑定方式和异常处理;分析了Thread.join()方法在多线程同步中的作用;并解释了ThreadLocal的使用场景,如数据库连接和session管理。

一.volatile和synchronize

1.volatile:读取数据时每次都从主内存中读取,每次写数据都要刷新到主内存,保证了数据的可见性和有序性。

2.synchronize:对需要操作的数据进行加锁,保证只有一个线程访问,保证数据的可见性和原子性,但是不保证数据的有序性。

二.等待通知机制

调用此类方法首先都要获得锁,即该语句要放到synchronize语句块内部。如果没有加锁会抛出异常:Exception in thread “main” java.lang.IllegalMonitorStateException

1.object.wait() 该方法会使线程放弃锁资源和cpu资源进入WAITING或者TIMED_WAITING状态。线程被加入到等待队列。

2.object.notify() 从等待队列中任意取一个线程唤醒,并将其放入同步队列中,唤醒哪个线程它是任意的。

3.object.notifyAll() 将等待队列里面的线程全部唤醒,加入到同步队列中。

三.管道输入输出流

对于Pipe类型的流,必须要先进行绑定,也就是调用connect()方法,如果没有将输入输出流进行绑定的话,对于流的访问会抛出IOException异常。
主要包括两类:
1.字节流
pipeOutputStream()
pipeInputStream()
2.字符流
pipeReader()
PipeWriter()

四.Thread.join()

用于等待其他线程执行完之后再继续工作。如果线程A执行了thread.join(),则A线程会等待thread线程终止后才继续执行后续内容。

五.ThreadLocal的使用 //主要用于数据库连接和session管理

ThreadLocal即是线程变量,是一个以ThreadLocal对象为键,任意对象为值的存储结构。
ThreadLocal类下有个ThreadLocalMap的子类,他是一个map类型结构,维护一个Entry(threadlocal,value)类型数组。
每个线程都拥有一个ThreadLocalMap类型的变量threadLocals,它存储了多个该线程拥有的(threadlocal,value)键值对。

源码比较简单,主要看一下set()和get()方法
set()方法

    public void set(T value) {
        Thread t = Thread.currentThread();//获取当前线程
        ThreadLocalMap map = getMap(t);//获取当前线程的ThreadLocalMap
        if (map != null) {
            map.set(this, value);//设置值
        } else {
            createMap(t, value);//建一个
        }
    }
    
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

get()方法

public T get() {
        Thread t = Thread.currentThread();//获取当前线程
        ThreadLocalMap map = getMap(t);//获取当前线程的ThreadLocalMap
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);//通过本ThreadLocal获取到Entry键值对
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;//通过Entry获取值
                return result;
            }
        }
        return setInitialValue();//如果获取到的Entry为空,则需要初始化,初始化时值为null,返回的值也为null
    }
 private T setInitialValue() {
        T value = initialValue();//查看源码返回的时null
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);//直接创建value为null
        }
        if (this instanceof TerminatingThreadLocal) {
            TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
        }
        return value;
    }

觉得笔者写的不错,请多多支持,点赞收藏加关注。
人非圣贤,孰能无过,有不准确的地方请多多指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值