简单的代码(我知道这是一个非常糟糕的代码,但我只是为示例编写的):
1 #include <mutex>
2 #include <iostream>
3 #include <thread>
4
5 std::mutex mu;
6
7 void myFunc(void) {
8 for (int i = 0; i < 100; ++i) {
9 mu.lock();
10 std::cout << "CHILD Thread: " << std::this_thread::get_id() << std::endl;
11 mu.unlock();
12 }
13 }
14
15 int main()
16 {
17 std::thread thr(myFunc);
18 for (int i = 0; i < 100; ++i) {
19 mu.lock();
20 std::cout << "MAIN Thread: " << std::this_thread::get_id() << std::endl;
21 mu.unlock();
22 }
23 thr.join();
24 return 0;
25 }返回此类输出:
1 MAIN Thread: 140581832210240
2 MAIN Thread: 140581832210240
3 MAIN Thread: 140581832210240
4 MAIN Thread: 140581832210240
5 MAIN Thread: 140581832210240
6 MAIN Thread: 140581832210240
7 MAIN Thread: 140581832210240
8 CHILD Thread: 140581814855424
9 CHILD Thread: 140581814855424
10 CHILD Thread: 140581814855424
11 CHILD Thread: 140581814855424
12 CHILD Thread: 140581814855424
13 CHILD Thread: 140581814855424
14 CHILD Thread: 140581814855424
15 CHILD Thread: 140581814855424
16 CHILD Thread: 140581814855424
17 CHILD Thread: 140581814855424
18 MAIN Thread: 140581832210240
19 MAIN Thread: 140581832210240
20 MAIN Thread: 140581832210240
21 MAIN Thread: 140581832210240
22 MAIN Thread: 140581832210240
23 CHILD Thread: 140581814855424
24 CHILD Thread: 140581814855424
25 CHILD Thread: 140581814855424
26 CHILD Thread: 140581814855424
27 CHILD Thread: 140581814855424
28 CHILD Thread: 140581814855424
29 CHILD Thread: 140581814855424
....... and so on在我看来--这个输出违背了多线程的意义,因为一个线程必须等待另一个线程很长时间。这个输出应该同时给我的孩子的cout,cout的主,cout的孩子,cout的主等等。我知道互斥不是公平分享共同资源的责任,但那是谁呢?我如何在我的程序中实现这一点?
谢谢。
编辑:将std::cout放入函数:
10 void common_cout(string msg) {
11 mu.lock();
12 std::cout << msg << std::endl;
13 mu.unlock();
14 }帮不上忙。
发布于 2016-07-08 22:03:43
原始代码在windows中也有相同的问题,但我切换到使用本机windows等效项,这个窗口示例的工作方式与您预期的一样,在两个线程之间交替使用。ReleaseMutex()的每个实例都会导致“其他”线程获取互斥并运行。主要而言,睡眠(2)是确保myFunc首先启动它的循环的一种简单方法。
我还为总共三个线程创建了一个主线程和两个线程的版本。循环按顺序进行,因此看起来Windows本机互斥锁是按照请求的顺序完成的。
对于循环类型或线程和/或进程之间的一般同步,每个线程或进程使用一个信号量更好,因为任何线程或进程都可以增加(释放/信号)任何信号量。这方面的问题是信号量不是标准线程接口的本机部分,需要一些互斥变量和条件变量的组合才能实现等效的信号量。Windows和posix支持本机信号量。
#include <iostream>
#include <windows.h>
static HANDLE mu; // handle: mutex
static HANDLE ht1; // handle: thread 1
static DWORD id1; // thread 1 id
DWORD WINAPI myFunc(LPVOID) {
for (int i = 0; i < 20; ++i) {
WaitForSingleObject(mu, INFINITE);
std::cout << "child thread: " << i << std::endl;
ReleaseMutex(mu);
}
return 0;
}
int main()
{
mu = CreateMutex(NULL,TRUE,NULL); // main owns mutex
ht1 = CreateThread(NULL, 0, myFunc, 0, 0, &id1);
Sleep(2); // make sure myFunc running
ReleaseMutex(mu); // release mutex
for (int i = 0; i < 20; ++i) {
WaitForSingleObject(mu, INFINITE);
std::cout << "main thread: " << i << std::endl;
ReleaseMutex(mu);
}
WaitForSingleObject(ht1, INFINITE);
CloseHandle(ht1);
CloseHandle(mu);
return 0;
}输出
child thread: 0
main thread: 0
child thread: 1
main thread: 1
...
child thread: 18
main thread: 18
child thread: 19
main thread: 193个线程示例:
#include <iostream>
#include <windows.h>
static HANDLE mu; // handle: mutex
static HANDLE ht0; // handle: thread 0
static HANDLE ht1; // handle: thread 1
static DWORD id0; // thread 0 id
static DWORD id1; // thread 1 id
DWORD WINAPI Thread0(LPVOID) {
for (int i = 0; i < 10; ++i) {
WaitForSingleObject(mu, INFINITE);
std::cout << "Thread0 : " << i << std::endl;
ReleaseMutex(mu);
}
return 0;
}
DWORD WINAPI Thread1(LPVOID) {
for (int i = 0; i < 10; ++i) {
WaitForSingleObject(mu, INFINITE);
std::cout << "Thread1 : " << i << std::endl;
ReleaseMutex(mu);
}
return 0;
}
DWORD WINAPI Thread2(LPVOID) {
for (int i = 0; i < 10; ++i) {
WaitForSingleObject(mu, INFINITE);
std::cout << "Thread2 : " << i << std::endl;
ReleaseMutex(mu);
}
return 0;
}
int main()
{
mu = CreateMutex(NULL,TRUE,NULL); // main owns mutex
ht0 = CreateThread(NULL, 0, Thread0, 0, 0, &id0);
ht1 = CreateThread(NULL, 0, Thread1, 0, 0, &id1);
Sleep(2); // let other threads get started
ReleaseMutex(mu); // release mutex
Thread2(0);
WaitForSingleObject(ht0, INFINITE);
WaitForSingleObject(ht1, INFINITE);
CloseHandle(ht0);
CloseHandle(ht1);
CloseHandle(mu);
return 0;
}输出
Thread0 : 0
Thread1 : 0
Thread2 : 0
Thread0 : 1
Thread1 : 1
Thread2 : 1
...
Thread0 : 9
Thread1 : 9
Thread2 : 9发布于 2016-07-08 16:09:46
我知道互斥不是公平分享共同资源的责任,但那是谁呢?
实际的调度是由操作系统完成的。
您还没有说过这是什么,但是通常不会在线程之间切换的频率过高,因为这样做效率很低(切换需要一些成本)。
换句话说,你对“公平”的想法--想必是严格的循环--每个线程轮流执行--这将是一种代价高昂的默认行为。无论如何,如果它是您想要的,您可以显式地对它进行编码。公平调度程序的通常目标是在运行的线程等待多长时间和在线程仍在执行(可能)有用的工作时抢占线程的频率之间进行某种权衡。
当然,操作系统的行为也取决于您有多少内核。你也没提过这个。
..。我如何在我的程序中实现这一点?
如果您在线程中做了一些合理的实际工作,您可能会发现您的调度程序的行为更符合您的喜好。这种人工测试很少给出有用的结果,特别是因为您在一个紧密的循环中执行少量的代码。
https://stackoverflow.com/questions/38270903
复制相似问题