T get_value()override { if (!is_ready_) { throw std::logic_error("Future not ready"); } if (exception_) { std::rethrow_exception(exception_); } return std::move(value_); }
voidfirst(function<void()> printFirst) { // printFirst() outputs "first". Do not change or remove this line. printFirst(); sem_post(&firstJobDone); }
voidsecond(function<void()> printSecond) { sem_wait(&firstJobDone); // printSecond() outputs "second". Do not change or remove this line. printSecond(); sem_post(&secondJobDone); }
voidfirst(function<void()> printFirst) { // printFirst() outputs "first". Do not change or remove this line. printFirst(); mx1.unlock(); }
voidsecond(function<void()> printSecond) { // printSecond() outputs "second". Do not change or remove this line. mx1.lock(); printSecond(); mx2.unlock(); }
classFoo { public: int k = 0; condition_variable cv; mutex mtx1, mtx2;
public: Foo() { } voidfirst(function<void()> printFirst) { // printFirst() outputs "first". Do not change or remove this line. printFirst(); k = 1; cv.notify_all(); }
voidsecond(function<void()> printSecond) { // printSecond() outputs "second". Do not change or remove this line. unique_lock<mutex> lock(mtx1); cv.wait(lock, [this]() { return k == 1; }); printSecond(); k = 2; cv.notify_all(); }
public: Foo() { } voidfirst(function<void()> printFirst) { // printFirst() outputs "first". Do not change or remove this line. printFirst(); num1.set_value(1); }
voidsecond(function<void()> printSecond) { int num = num1.get_future().get(); // printSecond() outputs "second". Do not change or remove this line. printSecond(); num2.set_value(1); }
public: Foo() { } voidfirst(function<void()> printFirst) { // printFirst() outputs "first". Do not change or remove this line. printFirst(); a = true; }
voidsecond(function<void()> printSecond) { while (!a) this_thread::sleep_for(chrono::milliseconds(1)); // printSecond() outputs "second". Do not change or remove this line. printSecond(); b = true; }
public: Foo() { } voidfirst(function<void()> printFirst) { // printFirst() outputs "first". Do not change or remove this line. printFirst(); a = true; }
voidsecond(function<void()> printSecond) { while (!a) this_thread::sleep_for(chrono::milliseconds(1)); // printSecond() outputs "second". Do not change or remove this line. printSecond(); b = true; }
classFooBar { private: int n; int k; mutex mtx; condition_variable cv;
public: FooBar(int n) { this->n = n; k = 1; }
voidfoo(function<void()> printFoo) {
for (int i = 0; i < n; i++) {
// printFoo() outputs "foo". Do not change or remove this line. unique_lock<mutex> lock(mtx); cv.wait(lock, [this]() { return k == 1; }); printFoo(); k = 2; cv.notify_all(); } }
voidbar(function<void()> printBar) {
for (int i = 0; i < n; i++) {
// printBar() outputs "bar". Do not change or remove this line. unique_lock<mutex> lock(mtx); cv.wait(lock, [this]() { return k == 2; }); printBar(); k = 1; cv.notify_all(); } } };
// printFoo() outputs "foo". Do not change or remove this line. int tmp = bb.get(); printFoo(); promise<int> tmp_b; future<int> tmp_bb; b = move(tmp_b); bb = move(tmp_bb); bb = b.get_future(); a.set_value(1); } }
voidbar(function<void()> printBar) {
for (int i = 0; i < n; i++) {
// printBar() outputs "bar". Do not change or remove this line. int tmp = aa.get(); printBar(); promise<int> tmp_a; future<int> tmp_aa; a = move(tmp_a); aa = move(tmp_aa); aa = a.get_future(); b.set_value(1); } } };
// printNumber(x) outputs "x", where x is an integer. voidzero(function<void(int)> printNumber) { for (int i = 1; i <= n; i++) { while (flag != 0) { this_thread::sleep_for(chrono::milliseconds(1)); } printNumber(0); if (i % 2) { flag = 1; } else { flag = 2; } } }
voideven(function<void(int)> printNumber) { for (int i = 2; i <= n; i += 2) { while (flag != 2) { this_thread::sleep_for(chrono::milliseconds(1)); } printNumber(i); flag = 0; } }
voidodd(function<void(int)> printNumber) { for (int i = 1; i <= n; i += 2) { while (flag != 1) { this_thread::sleep_for(chrono::milliseconds(1)); } printNumber(i); flag = 0; } } }; intmain() { ZeroEvenOdd zeroEvenOdd(2); thread t1(&ZeroEvenOdd::zero, &zeroEvenOdd, [&](int num) { cout << num << endl; }); thread t2(&ZeroEvenOdd::even, &zeroEvenOdd, [&](int num) { cout << num << endl; }); thread t3(&ZeroEvenOdd::odd, &zeroEvenOdd, [&](int num) { cout << num << endl; }); t1.join(); t2.join(); t3.join(); getchar(); return0; }
// printNumber(x) outputs "x", where x is an integer. voidzero(function<void(int)> printNumber) { for (int i = 1; i <= n; i++) { sem_wait(&zero1); printNumber(0); if (i % 2) { sem_post(&odd1); } else { sem_post(&even1); } } }
voideven(function<void(int)> printNumber) { for (int i = 2; i <= n; i += 2) {
// printNumber(x) outputs "x", where x is an integer. voidzero(function<void(int)> printNumber) { for (int i = 1; i <= n; i++) { unique_lock<mutex> lock(mtx); cv.wait(lock, [this]() { return flag == 0; }); printNumber(0); if (i % 2) flag = 1; else flag = 2; cv.notify_all(); } }
voideven(function<void(int)> printNumber) { for (int i = 2; i <= n; i += 2) { unique_lock<mutex> lock(mtx2); cv.wait(lock, [this]() { return flag == 2; }); printNumber(i); flag = 0; cv.notify_all(); } }
voidodd(function<void(int)> printNumber) { for (int i = 1; i <= n; i += 2) { unique_lock<mutex> lock(mtx1); cv.wait(lock, [this]() { return flag == 1; }); printNumber(i); flag = 0; cv.notify_all(); } } };
// printNumber(x) outputs "x", where x is an integer. voidzero(function<void(int)> printNumber) { for (int i = 1; i <= n; i++) { mtx.lock(); printNumber(0); if (i % 2) { mtx1.unlock(); } else { mtx2.unlock(); } } }
voideven(function<void(int)> printNumber) { for (int i = 2; i <= n; i += 2) { mtx2.lock(); printNumber(i); mtx.unlock(); } }
voidodd(function<void(int)> printNumber) { for (int i = 1; i <= n; i += 2) { mtx1.lock(); printNumber(i); mtx.unlock(); } } };
classH2O { public: mutex mtx1,mtx2; int cnt=2; H2O() { }
voidhydrogen(function<void()> releaseHydrogen){ mtx1.lock(); // releaseHydrogen() outputs "H". Do not change or remove this line. releaseHydrogen(); cnt--; if(cnt>0) mtx1.unlock(); if(cnt==0) mtx2.unlock(); }
voidoxygen(function<void()> releaseOxygen){ mtx2.lock(); // releaseOxygen() outputs "O". Do not change or remove this line. releaseOxygen(); cnt+=2; mtx1.unlock(); } };
Thread 3 (Thread 0x7f0846b3c700 (LWP 1407291)): #0 __lll_lock_wait (futex=futex@entry=0x5574527f2160 <mtx1>, private=0) at lowlevellock.c:52 #1 0x00007f084768f0a3 in __GI___pthread_mutex_lock (mutex=0x5574527f2160 <mtx1>) at ../nptl/pthread_mutex_lock.c:80 #2 0x00005574527ed74f in __gthread_mutex_lock (__mutex=0x5574527f2160 <mtx1>) at /usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h:749 #3 0x00005574527ed8a4 in std::mutex::lock (this=0x5574527f2160 <mtx1>) at /usr/include/c++/9/bits/std_mutex.h:100 #4 0x00005574527ed940 in std::lock_guard<std::mutex>::lock_guard (this=0x7f0846b3bdf0, __m=...) at /usr/include/c++/9/bits/std_mutex.h:159 #5 0x00005574527ed541 in taskB () at main.cpp:36 #6 0x00005574527ee526 in std::__invoke_impl<void, void (*)()> (__f=@0x557453d97008: 0x5574527ed4b1 <taskB()>) at /usr/include/c++/9/bits/invoke.h:60 #7 0x00005574527ee4be in std::__invoke<void (*)()> (__fn=@0x557453d97008: 0x5574527ed4b1 <taskB()>) at /usr/include/c++/9/bits/invoke.h:95 #8 0x00005574527ee450 in std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul> (this=0x557453d97008) at /usr/include/c++/9/thread:244 #9 0x00005574527ee40d in std::thread::_Invoker<std::tuple<void (*)()> >::operator() (this=0x557453d97008) at /usr/include/c++/9/thread:251 #10 0x00005574527ee3de in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run (this=0x557453d97000) at /usr/include/c++/9/thread:195 #11 0x00007f0847798df4 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6 #12 0x00007f084768c609 in start_thread (arg=<optimized out>) at pthread_create.c:477 #13 0x00007f08475b1353 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 2 (Thread 0x7f084733d700 (LWP 1407290)): #0 __lll_lock_wait (futex=futex@entry=0x5574527f21a0 <mtx2>, private=0) at lowlevellock.c:52 #1 0x00007f084768f0a3 in __GI___pthread_mutex_lock (mutex=0x5574527f21a0 <mtx2>) at ../nptl/pthread_mutex_lock.c:80 #2 0x00005574527ed74f in __gthread_mutex_lock (__mutex=0x5574527f21a0 <mtx2>) at /usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h:749 #3 0x00005574527ed8a4 in std::mutex::lock (this=0x5574527f21a0 <mtx2>) at /usr/include/c++/9/bits/std_mutex.h:100 #4 0x00005574527ed940 in std::lock_guard<std::mutex>::lock_guard (this=0x7f084733cdf0, __m=...) at /usr/include/c++/9/bits/std_mutex.h:159 #5 0x00005574527ed3f8 in taskA () at main.cpp:23 #6 0x00005574527ee526 in std::__invoke_impl<void, void (*)()> (__f=@0x557453d96eb8: 0x5574527ed368 <taskA()>) at /usr/include/c++/9/bits/invoke.h:60 #7 0x00005574527ee4be in std::__invoke<void (*)()> (__fn=@0x557453d96eb8: 0x5574527ed368 <taskA()>) at /usr/include/c++/9/bits/invoke.h:95 #8 0x00005574527ee450 in std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul> (this=0x557453d96eb8) at /usr/include/c++/9/thread:244 #9 0x00005574527ee40d in std::thread::_Invoker<std::tuple<void (*)()> >::operator() (this=0x557453d96eb8) at /usr/include/c++/9/thread:251 #10 0x00005574527ee3de in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run (this=0x557453d96eb0) at /usr/include/c++/9/thread:195 #11 0x00007f0847798df4 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6 #12 0x00007f084768c609 in start_thread (arg=<optimized out>) at pthread_create.c:477 #13 0x00007f08475b1353 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 1 (Thread 0x7f084733e740 (LWP 1407289)): #0 __pthread_clockjoin_ex (threadid=139673531045632, thread_return=0x0, clockid=<optimized out>, abstime=<optimized out>, block=<optimized out>) at pthread_join_common.c:145 #1 0x00007f0847799057 in std::thread::join() () from /lib/x86_64-linux-gnu/libstdc++.so.6 #2 0x00005574527ed648 in main () at main.cpp:47
(base) sv@sv-NF5280M5:/home/sv$ sudo gdb attach 1406920 [sudo] sv 的密码: GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty"for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration"for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>.
For help, type"help". Type "apropos word" to search for commands related to "word"... attach: 没有那个文件或目录. Attaching to process 1406920 [New LWP 1406921] [New LWP 1406922] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". __pthread_clockjoin_ex (threadid=139933978740480, thread_return=0x0, clockid=<optimized out>, abstime=<optimized out>, block=<optimized out>) at pthread_join_common.c:145 145 pthread_join_common.c: 没有那个文件或目录. (gdb) info threads Id Target Id Frame * 1 Thread 0x7f44eb185740 (LWP 1406920) "main" __pthread_clockjoin_ex (threadid=139933978740480, thread_return=0x0, clockid=<optimized out>, abstime=<optimized out>, block=<optimized out>) at pthread_join_common.c:145 2 Thread 0x7f44eb184700 (LWP 1406921) "main" __lll_lock_wait (futex=futex@entry=0x55d52319e1a0 <mtx2>, private=0) at lowlevellock.c:52 3 Thread 0x7f44ea983700 (LWP 1406922) "main" __lll_lock_wait (futex=futex@entry=0x55d52319e160 <mtx1>, private=0) at lowlevellock.c:52 (gdb) thread 2 [Switching to thread 2 (Thread 0x7f44eb184700 (LWP 1406921))] #0 __lll_lock_wait (futex=futex@entry=0x55d52319e1a0 <mtx2>, private=0) at lowlevellock.c:52 52 lowlevellock.c: 没有那个文件或目录. (gdb) bt # 函数调用栈 #0 __lll_lock_wait (futex=futex@entry=0x55d52319e1a0 <mtx2>, private=0) at lowlevellock.c:52 #1 0x00007f44eb4d60a3 in __GI___pthread_mutex_lock (mutex=0x55d52319e1a0 <mtx2>) at ../nptl/pthread_mutex_lock.c:80 #2 0x000055d52319974f in __gthread_mutex_lock (__mutex=0x55d52319e1a0 <mtx2>) at /usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h:749 #3 0x000055d5231998a4 in std::mutex::lock (this=0x55d52319e1a0 <mtx2>) at /usr/include/c++/9/bits/std_mutex.h:100 #4 0x000055d523199940 in std::lock_guard<std::mutex>::lock_guard (this=0x7f44eb183df0, __m=...) at /usr/include/c++/9/bits/std_mutex.h:159 #5 0x000055d5231993f8 in taskA () at main.cpp:23 #6 0x000055d52319a526 in std::__invoke_impl<void, void (*)()> (__f=@0x55d523aeeeb8: 0x55d523199368 <taskA()>) at /usr/include/c++/9/bits/invoke.h:60 #7 0x000055d52319a4be in std::__invoke<void (*)()> (__fn=@0x55d523aeeeb8: 0x55d523199368 <taskA()>) at /usr/include/c++/9/bits/invoke.h:95 #8 0x000055d52319a450 in std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul> (this=0x55d523aeeeb8) at /usr/include/c++/9/thread:244 #9 0x000055d52319a40d in std::thread::_Invoker<std::tuple<void (*)()> >::operator() (this=0x55d523aeeeb8) at /usr/include/c++/9/thread:251 #10 0x000055d52319a3de in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run (this=0x55d523aeeeb0) at /usr/include/c++/9/thread:195 #11 0x00007f44eb5dfdf4 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6 #12 0x00007f44eb4d3609 in start_thread (arg=<optimized out>) at pthread_create.c:477 #13 0x00007f44eb3f8353 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 (gdb) f 5 # 线程2的第5帧信息 #5 0x000055d5231993f8 in taskA () at main.cpp:23 23 std::lock_guard<std::mutex> lockB(mtx2)