并发编程
并发编程的目的是让程序执行更快,但是多线程并不一定比单线程执行快。比如多线程会遇到的问题有:上下文切换<单核、时间片>、死锁等。
上下文切换:
public class JavaMain { private static final int count = 1000; public static void main(String[] args) throws InterruptedException { work1(); work2(); } private static void work1() throws InterruptedException { System.out.println("start1 = " + System.currentTimeMillis()); Thread thread = new Thread(new Runnable() { @Override public void run() { int b = 0; for (int i = 0; i < 0; i++) { b -= i; } } }); thread.start(); int a = 0; for (int i = 0; i < 0; i++) { a += i; } thread.join(); System.out.println("end 1 = " + System.currentTimeMillis()); } private static void work2() { System.out.println("start2 = " + System.currentTimeMillis()); int b = 0; for (int i = 0; i < 0; i++) { b -= i; } int a = 0; for (int i = 0; i < 0; i++) { a += i; } System.out.println("end 2 = " + System.currentTimeMillis()); } }
运行结果:
start1 = 1498834716175
end 1 = 1498834716178
start2 = 1498834716179
end 2 = 1498834716179
如何减少上下文切换:
无锁并发编程、CAS算法、使用最少线程和使用协程。
死锁:
public class JavaMain { private static final String a = "A"; private static final String b = "B"; public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { synchronized (a) { try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (b) { System.out.println("end 1"); } } } }).start(); new Thread(new Runnable() { @Override public void run() { synchronized (b) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (a) { System.out.println("end 2"); } } } }).start(); } }
两个线程死锁
如何避免死锁:
1、一个线程同时拥有多个锁或锁内同时占多个资源,尽量保证每个锁只占一个资源。
2、lock.tryLock( ) 代替使用内部锁机制。
3、对于数据库,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败情况。