- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道异步不是并行的,但我现在遇到了一个非常有趣的情况。
async function magic(){
/* some processing here */
await async () => await prompt_for_user(); // 1st prompt
await async () => await prompt_for_user(); // 2nd prompt
}
magic(); // first
magic(); // second
magic(); // third
从上面的程序中,我们可以轻松预测所有提示会同时弹出。我尝试使用以下实现的队列来解决它:
const Queue = () => {
let promise;
return async (f) => {
while(promise) await promise;
promise = f();
const res = await promises;
promise = undefined;
return res;
};
};
const queue = Queue();
async function magic(){
/* some processing here */
await queue(async () => await prompt_for_user()); // 1st prompt
await queue(async () => await prompt_for_user()); // 2nd prompt
}
magic(); // first
magic(); // second
magic(); // third
这会阻止一次全部弹出提示。但还有第二个问题:
所以当第一个 magic()
被调用时。向用户显示提示 first.1
。程序继续并调用第二个 magic()
。另一个提示 second.1
正在等待第一个提示完成后再出现。然后程序继续,调用第三个 magic()
,并且 third.1
再次等待 first.1
完成。当 first.1
完成时,意味着用户已经输入了值,second.1
将首先弹出,但我希望 first.2
弹出先起来。
我知道一个明显的解决方案是一一等待魔法。但是这样就会失去js给我们带来的异步优势。如果提示前处理的魔法较多,则提示前需要一些时间。
想法?
1 Câu trả lời
由于在您发布信号量答案之前我无法理解您的总体目标,因此我将尝试回答的问题定义如下。
这是一个方案,以您发布的方案为模型,但它使用一系列 promise (不旋转或轮询标志)来强制序列化 prompt()
调用( >.start()
Và .end()
调用,同时允许所有其他操作并行运行。这对于 CPU 使用率来说应该会更加高效。
let Semaphore = (function() {
// private data shared among all instances
let sharedPromise = Promise.resolve();
return class Sempaphore {
constructor() {
let priorP = sharedPromise;
let resolver;
// create our promise (to be resolved later)
let newP = new Promise(resolve => {
resolver = resolve;
});
// chain our position onto the sharedPromise to force serialization
// of semaphores based on when the constructor is called
sharedPromise = sharedPromise.then(() => {
return newP;
});
// allow caller to wait on prior promise for its turn in the chain
this.start = function() {
return priorP;
}
// finish our promise to enable next caller in the chain to get notified
this.end = function() {
resolver();
}
}
}
})();
// use random times to test our async better
function prompt(tag, n) {
log(tag, 'input please: ', n);
return new Promise((resolve) => {
setTimeout(resolve, Math.floor(Math.random() * 1000) + 500);
});
};
function log(...args) {
if (!log.start) {
log.start = Date.now();
}
let diff = ((Date.now() - log.start) / 1000).toFixed(3);
console.log(diff + ": ", ...args);
}
function randomDelay(low = 500, high = 1000) {
return new Promise((resolve) => {
setTimeout(resolve, Math.floor(Math.random() * (high - low)) + low);
});
}
async function magic1(tag){
// declare semaphore before any async code to reserve your order for semaphored code below
let s = new Semaphore();
// whatever sync or async code you want here
log(tag, 'do some busy async work 1a');
await randomDelay(800, 1200);
log(tag, 'do some busy work 1b');
// start of our serialized critical section
await s.start();
await prompt(tag, 1);
await prompt(tag, 2);
s.end();
// end of our serialized critical section
// whatever sync or async code you want here
log(tag, 'do more busy work 1c');
await randomDelay();
}
async function magic2(tag){
let s = new Semaphore();
log(tag, 'do some busy async work 2a');
// this delay purposely causes magic2 async delay to be shorter
// than magic1 for testing purposes
await randomDelay(100, 750);
log(tag, 'do some busy work 2b');
await s.start();
await prompt(tag, 3);
await prompt(tag, 4);
s.end();
log(tag, 'do more busy work 2c');
await randomDelay();
}
Promise.all([
magic1("magic1a"),
magic1("magic1b"),
magic2("magic2a"),
magic2("magic2b")
]).then(() => {
log("all done");
}).catch(err => {
log("err: ", err);
});
这是一些示例输出(由于出于测试目的而进行的随机异步延迟,输出会略有不同)。但是,输入调用将始终按照完全相同的顺序:
0.000: magic1a do some busy async work 1a
0.003: magic1b do some busy async work 1a
0.004: magic2a do some busy async work 2a
0.004: magic2b do some busy async work 2a
0.600: magic2b do some busy work 2b
0.721: magic2a do some busy work 2b
0.829: magic1b do some busy work 1b
1.060: magic1a do some busy work 1b
1.061: magic1a input please: 1
2.179: magic1a input please: 2
2.860: magic1a do more busy work 1c
2.862: magic1b input please: 1
3.738: magic1b input please: 2
4.500: magic1b do more busy work 1c
4.502: magic2a input please: 3
5.845: magic2a input please: 4
6.497: magic2a do more busy work 2c
6.498: magic2b input please: 3
7.516: magic2b input please: 4
8.136: magic2b do more busy work 2c
9.097: all done
一些解释:
在代码中放置 let s = new Sempaphore();
的位置就是该函数“将自身放入队列”以进行序列化的位置,以便尚未将其自身放入队列中的东西在行中,它的关键部分被迫位于该函数的关键部分之后。这“保留”了一个队列位置,但实际上尚未开始关键部分。如果您有其他不确定的异步代码在关键部分之前运行,这一点很重要。您需要在异步代码之前保留排队位置,但直到关键部分之前才真正等待排队位置。
在函数中放置 await s.start();
的位置是您希望它实际等待关键部分的位置的位置。
放置 s.end()
的位置是关键部分的末尾(允许其他关键部分现在也可以在轮到它们时运行)。
此演示显示了在提示的关键部分之前和之后运行的异步代码。该代码可以与其他代码并行运行。
即使在同一关键部分(根据设计),非输入相关的异步操作也可以在输入提示之间交错。仅输入提示被强制序列化。
关于JavaScript、异步、锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47797221/
1. Khóa công bằng và khóa không công bằng 1.1 Tổng quan về khóa công bằng và khóa không công bằng Khóa công bằng: chỉ nhiều luồng lấy khóa theo thứ tự chúng áp dụng cho khóa. Khóa không công bằng: đề cập đến thứ tự mà nhiều luồng có được khóa, không theo thứ tự mà chúng áp dụng cho khóa. Có thể luồng áp dụng sau sẽ nhận được khóa trước hơn luồng áp dụng trước.
Đọc nội dung 1. Giới thiệu 2. Phân loại 3. Khóa toàn cục 4. Khóa bảng 5. Khóa bảng 6. Khóa siêu dữ liệu
Vì vậy, trong chương trình tôi đang viết, tôi có ba hàm, hãy gọi chúng là A, B và C để đơn giản. Mỗi chức năng cần truy cập vào tài nguyên X để hoạt động. Hạn chế là A và B không được phép chạy cùng lúc và phải được đồng bộ hóa đúng cách. Tuy nhiên, C có thể chạy đồng thời với A hoặc B.
Tôi đã nghe những từ này liên quan đến lập trình đồng thời, nhưng sự khác biệt giữa khóa, mutex và semaphore là gì? Câu trả lời hay nhất Khóa chỉ cho phép một luồng vào phần đã khóa và khóa này không được chia sẻ với bất kỳ tiến trình nào khác. Mutex giống như khóa, nhưng nó có thể áp dụng trên toàn hệ thống (được chia sẻ bởi nhiều quy trình).
Câu hỏi này đã có câu trả lời: Cách hiệu quả để triển khai mô hình singleton trong Java là gì? [đã đóng] (29 câu trả lời) Đã đóng
Câu hỏi này đã có câu trả lời: Cách hiệu quả để triển khai mô hình singleton trong Java là gì? [đã đóng] (29 câu trả lời) Đã đóng
Tôi có một vài câu hỏi về chủ đề trong tiêu đề. Đầu tiên, giả sử chúng ta sử dụng JDBC và có 2 giao dịch T1 và T2. Trong T1, chúng ta thực hiện câu lệnh select trên một hàng cụ thể. Sau đó chúng tôi thực hiện cập nhật trên hàng đó. Trong giao dịch T2, chúng tôi
Tôi muốn hàm của tôi chỉ chạy một lần. Điều này có nghĩa là nếu nhiều luồng gọi hàm này cùng một lúc, hàm sẽ chặn tất cả các luồng và chỉ cho phép luồng đó chạy. Câu trả lời hay nhất Có vẻ như bạn muốn quy trình được lưu trữ phải đồng bộ. Tại sao không đưa tính năng đồng bộ hóa vào ngay trong ứng dụng? pthread_tắt tiếng
if (runInDemoMode) { lock (this) { //Khởi tạo các bảng dCreator.create
Tôi tin rằng vấn đề của tôi có thể được trình bày bằng bất kỳ ngôn ngữ nào, nhưng để có một số "điểm neo", tôi sẽ mô tả nó bằng Java. Hãy xem xét tình huống sau: Tôi có một lớp PickyHost mở rộng Thread và thể hiện p của nó
Tôi biết rằng async không song song, nhưng bây giờ tôi đang phải đối mặt với một tình huống rất thú vị. hàm async magic(){ /* một số xử lý ở đây */ await async () =
Chúng tôi đang xây dựng một ứng dụng web bằng Scala, Play framework và MongoDB (với ReactiveMongo là trình điều khiển). Kiến trúc ứng dụng không bị chặn từ đầu đến cuối. Trong một số phần của mã, chúng ta cần truy cập
Tôi cần một khóa đơn giản với thời gian chờ JavaME (backport của concurrent.lock yêu cầu Java 1.3 đầy đủ). Nếu ai đó đã công bố mã khóa thử nghiệm cho JavaME, tôi muốn sử dụng mã đó. Khóa đã bị khóa
Theo boost: Để truy cập đối tượng, weak_ptr có thể được chuyển đổi thành shared_ptr bằng cách sử dụng bản sao shared_ptr
Có một câu hỏi về sự khác biệt giữa các phần Mutex và Critical, nhưng nó cũng không xử lý được Locks. Vì vậy, tôi muốn biết liệu các phần quan trọng có thể được sử dụng để đồng bộ hóa luồng giữa các quy trình hay không. Ý nghĩa của trạng thái có tín hiệu và không có tín hiệu là gì? Câu trả lời tốt nhất nằm trong Win
Ứng dụng phổ biến nhất của khóa là kiểm soát hàng tồn kho trong các tình huống có nhiều hoạt động đồng thời. Lần này chúng tôi chỉ giới thiệu sơ lược về khóa độc lập. Hãy xem trực tiếp mã: Mỗi lần có yêu cầu, hàng tồn kho sẽ giảm đi 1. Nếu hàng tồn kho là 1000, sau 1000 yêu cầu, hàng tồn kho sẽ trở thành 0.
Luồng và tiến trình 1. Luồng chia sẻ không gian địa chỉ của tiến trình đã tạo ra chúng và tiến trình có không gian địa chỉ riêng của nó 2. Luồng có thể truy cập tất cả dữ liệu của tiến trình và các luồng có thể truy cập lẫn nhau 3. Dữ liệu giữa các luồng là độc lập 4. Tiến trình con sao chép dữ liệu của luồng 5. Tiến trình con bắt đầu
**Tóm tắt: ** Những người cẩn thận hẳn đã nhận thấy rằng một số URL bắt đầu bằng https và một số bắt đầu bằng http. Sẽ có một ổ khóa nhỏ ở phía trước trang web bắt đầu bằng https. Tại sao lại thế? Bài viết này được chia sẻ từ Huawei Cloud Community "Bạn không biết rằng chứng chỉ SSL đã trở thành một điều cần thiết sao? Hãy đến và tìm hiểu
Tôi đang cố gắng triển khai một mutex (khóa) rất đơn giản trong C và tôi hơi bối rối. Tôi hiểu rằng mutex tương tự như semaphore nhị phân, ngoại trừ mutex còn áp dụng ràng buộc rằng luồng giải phóng khóa phải là luồng đã có được khóa gần đây nhất. Tôi không biết làm thế nào để theo dõi quyền sở hữu? Đây là những gì tôi đã làm cho đến nay
Sau khi đọc nhiều bài đăng và câu trả lời liên quan đến chủ đề trên, tôi vẫn muốn biết cơ sở dữ liệu SQL Server hoạt động như thế nào trong ví dụ sau: Giả sử chúng ta có một bảng có tên là t3: create table t3 (a int ,
Tôi là một lập trình viên xuất sắc, rất giỏi!