申請一塊記憶體,分10小塊, 回圈使用
寫執行緒先寫,之后讀執行緒讀取資料,使用鎖可以很容易的完成互斥。
假如我不使用鎖,完全使用int read_idx=0, int write_idx=0, 似乎可以完全代替鎖,請大家比較一下這種方式和鎖的優缺點?
下面是使用read_idx, write_idx的偽代碼。
write_thread(){
while(1){
if(write_idx!=read_idx){
memory[write_idx] = random_value;
}else
continue;
if((write_idx +1) == 10)
write_idx = 0;
else
write_idx++;
}
}
read_thread(){
while(1){
if(read_idx!=read_idx){
printf(memory[read_idx]);
}else
continue;
if((read_idx +1) == 10)
read_idx = 0;
else
read_idx++;
}
}
uj5u.com熱心網友回復:
老老實實加鎖uj5u.com熱心網友回復:
就要看這兩個執行緒是否會共享資料,從你的例程上看,不能代替鎖。還是建議加上鎖
uj5u.com熱心網友回復:
另外,這句代碼是不是有問題呢?if(read_idx!=read_idx){
uj5u.com熱心網友回復:
加鎖吧,一個簡單的例子,這段代碼
if(write_idx!=read_idx){
memory[write_idx] = random_value;
}else
判斷時候連個index不等,但判斷完,賦值之前,另外一個執行緒有操作,導致連個index相等了,那后面還會你想要的結果么?判斷到賦值并不是原子操作
uj5u.com熱心網友回復:
你在判斷值之后,在下一步代碼執行之前,你判斷的值就有可能在另一個執行緒被修改了。uj5u.com熱心網友回復:
如果是順序讀和順序寫是不用枷鎖的,需要用變數表明可讀位置和可寫位置uj5u.com熱心網友回復:
對不起,你的步驟不是原子步驟,錯誤。uj5u.com熱心網友回復:
樓上的大佬們都說全了,主要是判斷相等和賦值不是原子操作,無法保證index不變化uj5u.com熱心網友回復:
你這種方法和鎖的道理是一樣的,只是有這樣的可能,你寫的時候剛判斷index后,讀的執行緒也在運行,就改變了index的值uj5u.com熱心網友回復:
if((read_idx +1) == 10)read_idx = 0;
這里是坑,如果read_idx回圈完了,write還沒有開始,你就悲劇了。
還有就是你這是雙執行緒,也只適用于雙執行緒,如果是3執行緒或更多呢?
uj5u.com熱心網友回復:
if(write_idx!=read_idx)這里如果都沒有開始的話,永遠也開始不了。
uj5u.com熱心網友回復:
加鎖才是正道吧uj5u.com熱心網友回復:
可以這么說,沒有優點吧uj5u.com熱心網友回復:
不加鎖,會記憶體訪問沖突的uj5u.com熱心網友回復:
假如讀執行緒有操作,導致兩個index相等了,另外讀執行緒不會對記憶體進行讀取,所以感覺沒有問題。uj5u.com熱心網友回復:
只要判斷的時候沒有問題,其他時候改,不會受到影響,判斷陳述句半截應該不會被中斷。請舉例說明問題出在什么地方,謝謝。uj5u.com熱心網友回復:
寫的時候判斷完index后,讀執行緒就算改變了index值,也不會影響啊,因為讀的時候還會繼續判斷是否和寫index是否相等,才會去讀取資料。您可以舉個例子說一下上面的程式index問題出現在何處?謝謝
uj5u.com熱心網友回復:
不可以uj5u.com熱心網友回復:
參考下c++11 原子變數 自旋鎖的實作uj5u.com熱心網友回復:
不可以,你考慮問題不夠細,好好看看你的代碼,會有沖突uj5u.com熱心網友回復:
我看了半天,這些人都是沒讀完代碼的嗎?一個執行緒控制寫指標,一個執行緒控制讀指標,為啥會有沖突?都是一句不可以,不是原子操作,你倒是說說為啥不可以啊?uj5u.com熱心網友回復:
寫指標寫到一半被讀指標讀了,所以wrong!uj5u.com熱心網友回復:
只需要把write_idx, read_idx定義成atomic就可以了吧。也不需要用鎖。最初的代碼,有個地方打錯了,在讀執行緒中,判斷陳述句是
if(read_idx!=write_idx){因為帖子不提供編輯功能,特此更正。
atomic_int read_idx = 0;
atomic_int write_id = 0;
假設write早一步啟動,write_idx先變成1, 啟動的時候不會死鎖。
write_thread(){
while(1){
if(write_idx!=read_idx){
memory[write_idx] = random_value;
}else
continue;
if((write_idx +1) == 10)
write_idx = 0;
else
write_idx++;
}
}
read_thread(){
while(1){
if(read_idx!=write_idx){
printf(memory[read_idx]);
}else
continue;
if((read_idx +1) == 10)
read_idx = 0;
else
read_idx++;
}
}
uj5u.com熱心網友回復:
你這個只能說兩個執行緒互不干擾(不同的執行緒修改不同的變數,不發生沖突),并不能說和鎖等價。
但是你這樣又個隱患,就是如果read_idx==write_idx 就會死回圈,就是一直走你的continue分支,最終兩個index都沒能修改
uj5u.com熱心網友回復:
或許加個state(狀態)控制一下可能會好一些當然,如果要保證讀寫一致,還是需要鎖的,這里只是說明互不干涉,不等價于同步。
比如
volatile int running = 1, writing = 1, reading = 1;
int write_idx = 0, read_idx = 0, wcnt = 0, rcnt = 0;
class buff {
public:
int state;
char *ptr;
buff(int bufsize) {
state = 0;
ptr = new char[bufsize];
}
~buff() {
delete []ptr;
}
};
buff *memory[10] = {
new buff(255),
new buff(255),
new buff(255),
new buff(255),
new buff(255),
new buff(255),
new buff(255),
new buff(255),
new buff(255),
new buff(255)
};
void write_thread(){
while(running){
while(1) {
if (memory[write_idx]->state==0) break; //找到可寫
write_idx = (write_idx+1)%10;
}
wcnt++;
struct timespec tn;
clock_gettime(CLOCK_REALTIME, &tn);
sprintf(memory[write_idx]->ptr, "write-%d:%ld", write_idx, tn.tv_nsec);
printf("%s\n", memory[write_idx]->ptr);
memory[write_idx]->state = 1; //寫完修改為可讀
write_idx = (write_idx+1)%10;
}
writing = 0;
}
void read_thread(){
while(running){
while(1) {
if (memory[read_idx]->state==1) break; //找到可讀
read_idx = (read_idx+1)%10;
}
rcnt++;
printf("read-%d:%s\n", read_idx, memory[read_idx]->ptr);
memory[read_idx]->state = 0; //讀完后修改為可寫
read_idx = (read_idx+1)%10;
}
reading = 0;
}
int main() {
thread* t1 = new std::thread(&write_thread);
thread* t2 = new std::thread(&read_thread);
this_thread::sleep_for(chrono::milliseconds(10));
running = 0;
while (writing);
while (reading);
for (int i=0; i<10; i++) {
delete memory[i];
}
printf("write_time=%d, read_time=%d\n", wcnt, rcnt);
return 0;
}
uj5u.com熱心網友回復:
如果你說的10小塊中所謂"小塊"是指一個字長以內的型別,那是不需要加鎖,執行緒安全的,因為CPU一次處理的資料就是以字長為單位,其讀寫是原子性的。但它是不是如你所想的邏輯那樣運行那就不好說了。比如語法跟語意,語法上正確,語意上不見得正確。其它情況還得加鎖。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/71291.html
標籤:C++ 語言
下一篇:有沒有mil轉mm的原始碼學習
