Java并发编程读书笔记——并发编程的简述
日期: 2018-03-19 分类: 个人收藏 366次阅读
这是读这本书的第二遍,所以会在前面记录一些后面可能比较重要的点,也希望记录一下所学,能学到第一遍所不能理解和懵懂的东西...
1.上下文切换:
计算机单核处理器也支持多线程,是因为CPU通过给每一个线程分配CPU的时间片,即每个线程占用CPU的时间,这个时间非常短,所以会让我们以为是多个线程同时执行的。
当一个任务执行完当前的时间片,会保存当前的状态,等下一次切换回来的时候加载这个状态,以便继续执行。即任务从保存到再加载的过程就是一次上下文切换。
2.多线程并不一定比单线程快。
上面说到多线程是通过上下文切换来实现的,每一次上下文切换仍需要时间,所以多线程并不一定比单线程快。书上列举了一段代码,以及测试的过程,结果是当并发执行累加操作不超过百万次时,速度会比串行执行累加操作要慢。
3.减少上下文切换。
(1).无锁并发编程:采用一些方法来避免使用锁,如将数据的ID按照Hash算法去摸分段,不同的线程处理不同段的数据(ConcurrentHashMap的原理)
(2).CAS算法(很重要,后边慢慢会说到,着急的可以先去查查CAS)
(3).使用最少的线程:这个就不用多说了,减少多余的线程。
(4).协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。
4.死锁。
死锁这个东西,有一点线程基础的人应该都听说过,个人觉得对于死锁,应该随手要能写出来,但是要极力的去避免它,做到这样就够了。下面就写一段简单的死锁的代码:
package com.concurrent.lock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DeadLockDemo {
private static final Logger logger = LoggerFactory.getLogger(DeadLockDemo.class);
private String A = "A";
private String B = "B";
public static void main(String[] args) {
new DeadLockDemo().deadLock();
}
private void deadLock(){
new Thread(new Runnable() {
@Override
public void run() {
synchronized (A){ //当前线程握住A锁
try {
Thread.currentThread().sleep(2000); //沉睡2S,不释放锁
logger.info("线程1:要执行的代码块1");
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B){ //要去获取B锁,但是由于沉睡2S,被线程2获取拿住
logger.info("线程1:要执行的代码块2");
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (B){ //当前线程握住B锁
try {
Thread.currentThread().sleep(2000); //沉睡2S,不释放锁
logger.info("线程2:要执行的代码块1");
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (A){ //要去获取A锁,但是被线程1握住
logger.info("线程2:要执行的代码块2");
}
}
}
}).start();
}
}
上面的两个线程一个握住A锁,一个握住B锁,都想要对方的锁,从而形成死锁,执行结果:
下面是后面学习记录的Java并发编程:
标签:Java并发编程
上一篇: Hbase——HA搭建
精华推荐