网站运营需要什么行业技术,可以做交互的网站,dedecms小说网站模板下载,wordpress 模版 推荐并发编程的目的与挑战
并发编程的目的是为了让程序运行得更快。启动更多的线程并不一定就能让程序最大限度地并发执行。 希望通过多线程执行任务让程序运行得更快#xff0c;会面临非常多的挑战。比如#xff1a; 上下文切换的问题死锁的问题硬件和软件的资源限制问题上下文…并发编程的目的与挑战
并发编程的目的是为了让程序运行得更快。启动更多的线程并不一定就能让程序最大限度地并发执行。 希望通过多线程执行任务让程序运行得更快会面临非常多的挑战。比如 上下文切换的问题死锁的问题硬件和软件的资源限制问题上下文切换
单核处理器也支持多线程执行代码CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间因为时间片非常短所以CPU通过不停地切换线程执行让我们感觉多个线程是同时执行的时间片一般是几十毫秒ms。
CPU通过时间片分配算法来循环执行任务当前任务执行一个时间片后会切换到下一个任务。但是在切换前会保存上一个任务的状态以便下次切换回这个任务时可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。
上下文切换也会影响多线程的执行速度。
如何减少上下文切换
减少上下文切换的方法有 无锁并发编程、CAS算法、使用最少线程 和 使用协程。
无锁并发编程。多线程竞争锁时会引起上下文切换所以多线程处理数据时可以用一些办法来避免使用锁如将数据的ID按照Hash算法取模分段不同的线程处理不同段的数据。
CAS算法。Java的Atomic包使用CAS算法来更新数据而不需要加锁。
使用最少线程。避免创建不需要的线程比如任务很少但是创建了很多线程来处理这样会造成大量线程都处于等待状态。
使用协程在单线程里实现多任务的调度并在单线程里维持多个任务间的切换。
死锁
死锁的简述就是俩个线程相互持有对方需要的资源并且又同时等待对方释放资源导致俩个线程相互僵持谁也不肯让谁。
死锁的定义死锁是指两个或两个以上的进程在执行过程中由于竞争资源或者由于彼此通信而造成的一种阻塞的现象若无外力作用它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁这些永远在互相等待的进程称为死锁进程。
我们可以通过一个小故事理解死锁。就是指有两个人他们在一起吃饭但是呢筷子不够A这个人有一支筷子B这个人也有一支筷子假如A要吃饭的时候B把筷子给了A这样A就吃上了饭同理B要吃饭的时候A把筷子给了B这样B也吃上了饭如果要是这样的话就没有我们什么事了但是有一天有一道菜非常好吃A、B都想先吃A向B拿筷子B也先向A拿筷子。两人都不愿意把筷子给对方那只能一直耗着等着那么我们就可以说他们两个死锁了。
死锁程序
那么如何使用java来编写一个死锁程序呢。简单来说就是在同步代码块中嵌套同步代码块两个同步代码块应用了两个不同的锁。A线程的第一个同步代码块用到了锁A第二个同步代码块用到了锁B。B线程第一个同步代码块用到了锁B第二个同步代码块用到了锁A。这样当A线程运行的时候先用了锁A还没有用到锁B的时候B线程也启动了用到了锁B,这时A线程要用锁B然而这时B线程却已经占用了锁B,而B线程继续运行需要锁A可是A线程已经占用了锁B这样话这两个线程就出现了死锁。
示例
package com.zsh;/*** 死锁:就是同步代码块中嵌套另外一个同步代码块* * author 小行**/
public class DeadLockDemo {public static void main(String[] args) {// 创建两个线程DeadLockThread dlt1 new DeadLockThread(false);DeadLockThread dlt2 new DeadLockThread(true);// 启动线程new Thread(dlt1).start();new Thread(dlt2).start();}
}class DeadLockThread implements Runnable {// 标记变量private boolean flag;public DeadLockThread(boolean flag) {super();this.flag flag;}public void run() {// dlt1线程执行该方法if (flag) {synchronized (ThreadLock.locka) {System.out.println(if locka!);synchronized (ThreadLock.lockb) {System.out.println(if lockb!);}}} // dlt2线程执行该方法else {synchronized (ThreadLock.lockb) {System.out.println(else lockb!);synchronized (ThreadLock.locka) {System.out.println(else locka!);}}}}
}class ThreadLock {static Object locka new Object();static Object lockb new Object();
}
程序运行之后会出现死锁的情况希望大家可以通过这个例子深入理解死锁。
避免死锁的几个常见方法
避免一个线程同时获取多个锁。
避免一个线程在锁内同时占用多个资源尽量保证每个锁只占用一个资源。
尝试使用定时锁使用lock.tryLocktimeout来替代使用内部锁机制。
对于数据库锁加锁和解锁必须在一个数据库连接里否则会出现解锁失败的情况。
资源限制的挑战
硬件资源限制有带宽的上传/下载速度、硬盘读写速度和CPU的处理速度。
软件资源限制有数据库的连接数和socket连接数等。
如何解决资源限制的问题
对于硬件资源限制可以考虑使用集群并行执行程序。比如使用ODPS、Hadoop或者自己搭建服务器集群。
对于软件资源限制可以考虑使用资源池将资源复用。比如使用连接池将数据库和Socket连接复用或者在调用对方webservice接口获取数据时只建立一个连接。
在资源限制情况下进行并发编程
根据不同的资源限制调整程序的并发度比如下载文件程序依赖于两个资源——带宽和硬盘读写速度。有数据库操作时涉及数据库连接数如果SQL语句执行非常快而线程的数量比数据库连接数大很多则某些线程会被阻塞等待数据库连接。
了解更多关注我哟