(一)并发编程的挑战

并发编程的目的是为了充分利用硬件资源,让程序跑的更快,但并不意味着开启更多的线程就能够实现这个目的,还需要考虑上下文切换、死锁的问题。

1.1 上下文切换

CPU通过时间片分配的方式来同时执行多个任务,一个任务执行一个时间片以后保存当前任务信息,然后加载另一个任务信息并切换到另一个任务,这就是一次上下文切换的过程。
减少上下文切换次数方法:

  • 无所并发编程,多线程竞争锁会引起上下文切换,可以采取分段加锁;
  • CAS算法,Atomic包使用CAS来更新数据;
  • 使用最小线程,避免创建不必要线程;
  • 协程,单线程实现多任务调度;
1.2 死锁
public class DeadLockDemo {
	private static String A = "A";
	private static String B= "B";
	
	public static main(String[] args) {
		new DeadLockDemo().deadLock();
	}
	
	private void deadLock() {
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				// 获取锁 A
				synchronized (A) {
					try {
						// 休眠2秒再去获取锁B
						Thread.currentThread().sleep(2000);
					} catch(InterruptedException ie) {
						e.printStackTrace();
					}
					// 获取锁B,此时线程t2可能已经获取到了锁B,所以在此等待锁B
					synchronized (B) {
						System.out.println(1);
					}
				}
			}
		});
	Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				// 获取锁B
				synchronized (B) {
					// 获取锁A,此时线程t1已经获取到了锁A,所以在此等待锁A
					synchronized (A) {
						System.out.println(2);
					}
				}
			}
		});
		t1.start();
		t2.start();
	}
}

以上示例演示了造成死锁的过程:获取锁A的线程等待锁B,获取锁B的线程等待锁A,导致两线程同时等待,无法继续执行。
避免死锁的几个方法:

  • 避免一个线程同时获取多个锁;
  • 避免一个线程同时占用多个资源;
  • 使用锁时,使用lock.tryLock(timeout)机制,超时获取不到则返回;
  • 数据库锁,加锁和解锁必须在同一线程里;
1.3 资源限制

网络带宽、CPU、文件等资源限制,考虑使用“池化技术”,比如线程池、数据库连接池、Socket池。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值