JAVA并发编程基础

Thread的状态

在Thread类中枚举State定义了线程的6种状态

public enum State {
    //创建线程实例
    NEW,
    //执行线程任务
    RUNNABLE,
    //等待监听锁
    BLOCKED,
    //调用了wait(),等待别的线程唤醒
    WAITING,
    //调用了wait(long)
    TIMED_WAITING,
    //线程任务执行完成
    TERMINATED;
}

 

线程池

Executors中提供了几种创建线程池的API

newSingleThreadExecutor:单线程的线程池

newFixedThreadPool:指定数量的定长线程池

newCachedThreadPool:最大线程数量为Integer.MAX_VALUE的线程池

newScheduledThreadPool:可定时执行任务的线程池,最大线程数量为Integer.MAX_VALUE

这几种方式创建的线程池的背后基本都是创建ThreadPoolExecutor的对象实例,需要注意的是这些线程池用于存放

线程任务的队列可近似认为是无限大的(队列长度为Integer.MAX_VALUE)。如果线程任务过多会导致内存溢出,所以

最好是自己来创建ThreadPoolExecutor实例来定义线程池。

 

volatile

当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去主存中读

取新值,这就保证了可见性。volatile不能保证原子性,如i++这样的操作都不是原子操作,因为他们都进行了多次原子操作,

多个线程同时获取到i的值。

 

ThreadLocal

每个线程持有变量的一份副本,各个线程操作的是本地内存中的变量。

ThreadLocal的set方法中,获取当前线程的ThreadLocalMap对象,然后将变量设置到当前线程的ThreadLocalMap对象中。

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
}

 

synchronized

在jdk1.5之前,对并发安全问题可以通过synchronized关键字对代码块进行加锁,但这是一种重量级锁,性能效率比较差。

在这之后,jdk对其进行了优化,根据多线程争夺锁的情况产生不同的状态锁。

自旋锁:当前线程竞争锁失败时,不直接阻塞自己,而是自旋一会,在自旋的同时重新竞争锁,如果自旋结束前获得了锁,

那么锁获取成功;否则,自旋结束后阻塞自己。

偏向锁:如果不仅仅没有实际竞争,自始至终,使用锁的线程都只有一个。轻量级锁每次申请、释放锁都至少需要一次CAS,

但偏向锁只有初始化时需要一次CAS。只需要在Mark Word中CAS记录owner(本质上也是更新,但初始值为空),如果记录

成功,则偏向锁获取成功,记录锁状态为偏向锁,以后当前线程等于owner就可以零成本的直接获得锁;否则,说明有其他线

程竞争,膨胀为轻量级锁。

轻量级锁:假设没有实际的锁竞争。使用轻量级锁时,不需要申请互斥量,仅仅将Mark Word中的部分字节CAS更新指向线程

栈中的Lock Record,如果更新成功,则轻量级锁获取成功,记录锁状态为轻量级锁;否则膨胀为重量级锁。

 

Lock

jdk1.5之后提供了一种显式锁,通过api的方式去对系统资源加锁和释放锁,对锁的控制更加细化,而且还提供了读写锁,支持

并发下读状态的资源共享。

ReentrantLock中的加锁操作实际调用的是Sync的lock方法,Sync有公平锁和非公平锁,无参的构造方法是非公平锁的实现

NonfairSync.lock()方法中else分支调用AbstractQueuedSynchronizer的acquire方法,我直接把那部分代码放过来了

public void lock() {
    sync.lock();
}

static final class NonfairSync extends Sync {

    final void lock() {
        if (compareAndSetState(0, 1))
            //通过底层的CAS操作,成功则设置当前线程获得独占锁
            setExclusiveOwnerThread(Thread.currentThread());
        else {
            /**
               tryAcquire方法,尝试获取独占锁,为true返回
               addWaiter,创建一个线程节点node,添加到虚拟队列中(不存在实例,只有节点关联)
               acquireQueued,for (;;)死循环,直到node节点的线程获取到锁
               假如acquireQueued返回true,代表线程被中断,执行selfInterrupt
            */
             if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                selfInterrupt();
        }    
    }

    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
    
}

 

线程通信工具类

CountDownLatch:可以把它看作一个计数器,只不过这个计数器的操作是原子操作,当count的值为零时当前线程继续运行

CyclicBarrier:栅栏类似于闭锁,它能阻塞一组线程直到某个事件的发生, 如开启3个线程等到某一时刻再同时去执行操作

Semaphore:synchronized 的加强版,作用是控制线程的并发数量。就这一点而言,单纯的synchronized 关键字是实现不了的。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值