1.线程上下文切换
即使是单核cpu也能执行多线程代码,通过每个线程非配cpu时间片来实现,时间片是分配给线程的时间,时间一般几十毫秒,让我们感觉是多线程执行的
2.多线程一定快么
不一定,多线程涉及到线程的创建和上下文切换的开销
3.如何减少上下文切换
无锁并发编程:例数据i的id按hash算法取模,不同的线程处理不同段的数据
cas算法:使用Java的Atomic包使用cas算法更新数据,不需要加锁
使用最少线程:避免创建不需要的线程,任务很少,创建了大量的线程处理,会导致大量的线程处于等待状态
协程:单线程实现多任务的调度,单线程维持多个任务的切换
4.死锁
1)死锁示例
public class DeadlockTest { private static String A = "A"; private static String B = "B"; public static void main(String[] args) { new DeadlockTest().deadLock(); } private void deadLock(){ Thread t1 = new Thread(new Runnable() { @Override public void run() { synchronized (A) { try { Thread.currentThread().sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (B) { System.out.println("1"); } } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (B) { synchronized (A) { System.out.println("2"); } } } }); t1.start(); t2.start(); } }
2)避免死锁的常用方法
避免一个线程同时获取多个锁
避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源
尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁
对于数据库锁。加锁或解锁必须在一个数据库连接里,否则会出现解锁失败的情况
5.资源限制的挑战
1)什么是资源限制
在进行并发编程时,程序的执行速度受限于计算机硬件或软件资源,如服务器带宽2mb/s,资源下载速度1md/s,系统启动10个线程,下载速度也不会变成10mb/s.
2)资源限制的问题
代码串行变成并行,如果受限于资源,仍然在串行执行的话反而更慢,增加了上下文切换和资源调度的时间。
3)如何解决资源限制的问题
集群并发执行,不同机器处理不同的数据
4)资源限制的情况下并发编程
根据不同资源限制程序的并发度,比如下载文件依赖带宽和硬盘读取速度,要根据带宽或硬盘读取速度限制使用的线程数,数据库操作涉及数据库连接数数,线程数比数据库连接数大很多,sql执行速度很快,那么线程会阻塞等待数据库连接,所以要根据资源来创建对应数量的线程。