并发控制原理以及PV代码实现分析
时间: 2023-08-02 20:37:15 浏览: 56
并发控制原理是指在多个进程或线程同时访问共享资源时,如何保证数据的一致性和正确性。常见的并发控制方法有互斥锁、读写锁、信号量等。
其中,信号量是一种经典的并发控制方法,它是一个计数器,用于控制多个进程或线程对共享资源的访问。信号量的PV操作包括两个操作:
P操作:如果信号量的值大于0,则将其减1并继续执行;如果值为0,则进程或线程被阻塞,直到信号量的值为非0。
V操作:将信号量加1,表示已经使用完共享资源。
下面是一个简单的PV操作的代码实现:
```
// 信号量的初始值为1
int semaphore = 1;
// P操作
void P() {
while (semaphore <= 0) {
// 等待信号量的值为非0
}
semaphore--;
}
// V操作
void V() {
semaphore++;
}
```
上述代码中,P操作会通过一个while循环来检查信号量的值是否为非0,如果为0则等待,直到值为非0才执行信号量的减1操作。V操作则是将信号量的值加1,表示已经使用完共享资源。
这只是一个简单的PV操作的代码实现,实际使用时还需要考虑多个进程或线程的并发访问,以及可能出现的死锁等问题。
相关问题
讲述一下promise的并发控制实现原理及代码
Promise并发控制是一种控制同时执行的异步任务数量的方法,它可以帮助我们更好地管理异步操作并避免资源浪费和性能问题。实现Promise并发控制的方法有很多种,下面是其中一种基于Promise的实现方式。
具体实现思路如下:
1. 定义一个函数 `limit`,接收两个参数:`pool` 和 `limitNum`,其中 `pool` 表示要执行的异步任务数组,`limitNum` 表示最大并发数量。
2. 创建一个 `results` 数组,用于存储所有异步任务的执行结果。
3. 创建一个 `runningCount` 变量,用于记录当前正在执行的异步任务数量。
4. 创建一个 `execute` 函数,用于执行异步任务,它接收一个 `task` 参数,表示要执行的异步任务。
5. 在 `execute` 函数中,使用 `Promise.resolve` 包装异步任务,并在 `then` 方法中执行任务并将结果存储到 `results` 数组中。
6. 在 `then` 方法中,将 `runningCount` 减 1,表示当前已执行完一个异步任务。
7. 在 `limit` 函数中,使用 `while` 循环遍历 `pool` 数组,如果当前正在执行的异步任务数量小于最大并发数量 `limitNum`,则调用 `execute` 函数执行下一个异步任务。
8. 在 `execute` 函数中,如果 `pool` 数组中还有待执行的异步任务,则继续调用 `execute` 函数递归执行任务。
9. 在 `limit` 函数中,使用 `Promise.all` 等待所有异步任务执行完毕,并返回最终的结果数组。
具体代码实现如下:
```javascript
function limit(pool, limitNum) {
let results = [];
let runningCount = 0;
function execute(task) {
runningCount++;
return Promise.resolve(task())
.then(result => {
results.push(result);
runningCount--;
if (pool.length > 0) {
execute(pool.shift());
}
});
}
while (runningCount < limitNum && pool.length > 0) {
execute(pool.shift());
}
return Promise.all(results);
}
```
使用示例:
```javascript
let tasks = [task1, task2, task3, task4, task5];
limit(tasks, 2).then(results => {
console.log(results);
});
```
上述代码中,`tasks` 数组中存储了五个异步任务,最大并发数量为 2。调用 `limit` 函数后,它会自动控制异步任务的并发数量,等待所有任务执行完毕后返回结果数组。
promise实现并发控制
使用Promise实现并发控制时,可以维护一个任务队列和一个并发池。首先将所有的任务放入任务队列中,然后从任务队列中取出一定数量的任务放入并发池中执行。当有任务执行完成后,从并发池中移除该任务,并将任务队列中的下一个任务放入并发池中执行。通过这种方式,可以实现对并发数量的控制。具体实现可以参考以下代码:
```
function sendRequest(requestList, limits, callback) {
const promises = []; // 维护一个promise队列
const pool = new Set(); // 当前的并发池,用Set结构方便删除
// 开始并发执行所有的任务
for (let request of requestList) {
// 开始执行前,先await判断当前的并发任务是否超过限制
if (pool.size >= limits) {
// 这里因为没有try catch,所以要捕获一下错误,不然影响下面微任务的执行
await Promise.race(pool).catch(err => err); }
const promise = request(); // 拿到promise
// 删除请求结束后,从pool里面移除
const cb = () => {
pool.delete(promise);
};
// 注册下then的任务
promise.then(cb, cb);
pool.add(promise);
promises.push(promise);
}
// 等最后一个for await结束,这里是属于最后一个await后面的微任务
// 注意这里其实是在微任务当中了,当前的promises里面是能确保所有的promise都在其中(前提是await那里命中了if)
Promise.allSettled(promises).then(callback, callback);
}
```