簡體   English   中英

如何在不使用 pthread_join() 的情況下同步線程?

[英]How do I synchronize the threads without using pthread_join()?

我創建了一個簡單的 C++ 程序,用於日志記錄。 我正在 for 循環中創建線程,該循環在test.cpp運行 1000 次,這是驅動程序文件。 pthread_create調用打印功能tt.cpp其中寫入參數即i中的輸入,在file.txt 我希望同步線程。

我曾嘗試使用同步線程的pthread_join ,但我希望在不使用 join 的情況下同步線程。

我知道如果一個線程被鎖定,很多線程將等待直到它被解鎖,並且在該線程被解鎖后,任何一個等待的線程都會鎖定該函數。 因此,我嘗試在tt.cpp使用靜態整數變量並嘗試將其與輸入參數進行比較,以便我可以使用pthread_cond_waitpthread_wait_signal但我在比較時遇到了分段錯誤。

 /* if(j == *((int *)input)))
    This comparison gave me a segmentation fault */


-------------------------test.cpp---------------------------------
#include "thr.h"


pthread_mutex_t loc;
FILE *thePrintFile = NULL;

int main()
{
    pthread_mutex_init(&loc,NULL);

    pthread_t p;
    thePrintFile = fopen("file.txt","r+");
    for(int i =0; i<1000;i++)
    {
        pthread_create(&p,NULL,print,(void *)i);
    }
    for(int k = 0; k<100000;k++);
    /* i have used it to ensure that the main thread 
       doesn't exit before the pthreads finish writing */
    return 0;

}

    ------------------------tt.cpp------------------------------------
    #include "thr.h"

    extern pthread_mutex_t loc;
    extern FILE *thePrintFile;

    void* print(void *input)
    {
        if(pthread_mutex_trylock(&loc) == 0)
        {   

            fprintf(thePrintFile,"%s%d\n",(int *)input);
            fflush(thePrintFile);
            pthread_mutex_unlock(&loc);
        }   
    }

    -----------------------------thr.h--------------------------------
    #ifndef THR_H_INCLUDED
    #define THR_H_INCLUDED

    void* print(void *input);

    #endif

下面給出的是 file.txt 的一部分。

1
5
9
10
11
12
13
14
15
16
18
19
20
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
21
201
202

要正確同步線程,您需要使用同步設備,例如條件變量 由於您使用的是 C++,因此最好使用其內置線程而不是原始 pthread API。

例如,此代碼同步 1000 個線程,以便每個線程使用條件變量和互斥對打印自己的 ID,以確保按順序打印 ID,由所有共享的單獨變量跟蹤。 它不是很有效,因為所有線程都為同一個互斥體而斗爭,但它可以正常工作。 可以通過為每個線程創建一個條件變量來提高效率,但正確執行它需要更好地理解您的實際用例。

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include <vector>

static std::mutex mutex;
static std::condition_variable condvar;
static int whos_next;

static void work(int id) {
  std::unique_lock<std::mutex> lock{mutex};
  // wait for our turn
  condvar.wait(lock, [=]() { return whos_next == id; });
  // it's our turn now - print our thread ID
  std::cout << id << '\n';
  ++whos_next;
  condvar.notify_all();    // notify the next thread to run
}

int main() {
  std::vector<std::thread> threads;
  for (int i = 0; i < 1000; i++)
    threads.push_back(std::thread([=]() { work(i); }));

  for (auto &t: threads)
    t.join();
}

請注意,上述代碼對join的使用不是為了使線程彼此同步(它們使用互斥鎖/條件在它們之間進行同步),而是出於其預期目的:在退出main()之前等待線程完成。 C++ 甚至要求您在銷毀std::thread對象之前執行此操作,因此刪除連接會導致程序終止。 您可以輕松證明線程不依賴於join進行同步,例如通過在 join 之前插入 sleep 或以相反的順序加入它們。

我在您的代碼中看到多個問題。

  • 您表明您在某條線上遇到了分段錯誤。 該行不在您發布的實際代碼中。
  • 您的打印部分有一個 void * 返回類型,但您沒有返回任何內容。
  • 您將 int 轉換為 void *。 指針的大小可能與 int 的大小不同。 將您的打印函數參數改為 int 。 那么演員表是不必要的。
  • 您不能同時將 1000 個線程寫入同一個文件。 所以在這種情況下沒有理由創建線程,因為無論如何你必須順序執行它們。 但如果你這樣做了,那么你必須加入他們。

然后讓我們看一下您嘗試進行的比較:

if(j == *((int *)input)))

j 顯然是整數。 輸入為空 *。 在基礎輸入是int。 因為不能保證將 int 轉換為 void * 是安全的,所以將其轉換回也不安全。 想象一下 int 是 64 位,指針是 32 位。 如果您將 int 轉換為 void * 您將丟失 32 位。 然后你從 32 位轉換到 64 位,所以你添加了 32 位的 0。 顯然,這會帶來問題。

考慮使用 C++11,這將大大改進您的代碼。 https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM