Odd even number printing using thread我遇到了这个问题,想要用C ++讨论解决方案。我能想到使用2个二进制信号量奇数和偶数信号量。甚至信号量初始化为1,奇数初始化为0.
**T1 thread function**
funOdd()
{
wait(even)
print odd;
signal(odd)
}
**T2 thread function**
funEven()
{
wait(odd)
print even
signal(even)
}
除此之外,如果我的函数只生成数字,并且有第三个线程T3将打印这些数字,那么什么应该是理想的设计?我使用了一个数组,其中奇数将被放置在奇数位置,偶数将被放置在偶数位置。 T3将从这个数组读取这将避免任何线程安全在这个数组上,如果T3没有找到任何索引,那么它将等待该索引被填充。另一种解决方案可以是使用具有互斥的队列,该互斥可以在插入时由T1和T2使用。
请评论此解决方案,以及如何提高效率。
编辑以使问题更加清晰:总体问题是我有两个生产者(T1,T2)和一个消费者(T3),而我的生产者是相互依赖的。
答案 0 :(得分:2)
使用condition_variable
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mu;
std::condition_variable cond;
int count = 1;
void PrintOdd()
{
for(; count < 100;)
{
std::unique_lock<std::mutex> locker(mu);
cond.wait(locker,[](){ return (count%2 == 1); });
std::cout << "From Odd: " << count << std::endl;
count++;
locker.unlock();
cond.notify_all();
}
}
void PrintEven()
{
for(; count < 100;)
{
std::unique_lock<std::mutex> locker(mu);
cond.wait(locker,[](){ return (count%2 == 0); });
std::cout << "From Even: " << count << std::endl;
count++;
locker.unlock();
cond.notify_all();
}
}
int main()
{
std::thread t1(PrintOdd);
std::thread t2(PrintEven);
t1.join();
t2.join();
return 0;
}
答案 1 :(得分:1)
解决方案基于C ++ 11关键代码部分,即mutex。
这是工作代码,然后是解释。
using namespace std;
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
std::mutex mtx;
void oddAndEven(int n, int end);
int main()
{
std::thread odd(oddAndEven, 1, 10);
std::thread Even(oddAndEven, 2, 10);
odd.join();
Even.join();
return 0;
}
void oddAndEven(int n, int end){
int x = n;
for (; x < end;){
mtx.lock();
std::cout << n << " - " << x << endl;
x += 2;
mtx.unlock();
std::this_thread::yield();
continue;
}
}
线程奇数进入方法oddAndEven,起始编号为1,因此他是奇数。他是第一个获得锁定mtx.lock()
。
同时,线程 Even 也尝试获取锁,但线程 odd 首先获取它,因此线程 Even 等待。
回到线程 odd (有锁),他打印数字1并用mtx.unlock()
释放锁。此时,我们希望线程 Even 获取锁定并打印2,因此我们通过编写std::this_thread::yield()
通知线程甚至。然后线程 Even 也会这样做。
答案 2 :(得分:1)
这是您可以参考的最简单的解决方案:
#include<iostream>
#include<mutex>
#include<pthread.h>
#include<cstdlib>
int count=0;
using namespace std;
mutex m;
void* printEven(void *a)
{
while(1)
{
m.lock();
if(count%2==0)
{
cout<<" I am Even"<<count<<endl;
count++;
}
if(count==100)
break;
m.unlock();
}
}
void* printOdd(void *b)
{
while(1)
{
m.lock();
if(count%2!=0)
{
cout<<"I am odd"<<count<<endl;
count++;
}
if(count>100)
break;
m.unlock();
}
}
int main()
{
int *ptr = new int();
pthread_t thread1, thread2;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&thread1,&attr,&printEven,NULL);
pthread_create(&thread2,&attr,&printOdd, NULL);
pthread_join(thread1,&ptr);
pthread_join(thread2,&ptr);
free(ptr);
}
答案 3 :(得分:1)
使用条件变量的解决方案。
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex oddevenMu;
condition_variable condVar;
int number = 1;
void printEvenOdd(bool isEven, int maxnubmer)
{
unique_lock<mutex> ul(oddevenMu);
while (number < maxnubmer)
{
condVar.wait(ul, [&]() {return number % 2 == isEven;});
cout << number++ << " ";
condVar.notify_all();
}
}
int main(string args[])
{
thread oddThread(printEvenOdd, false, 100);
thread evenThread(printEvenOdd, true, 100);
oddThread.join();
evenThread.join();
return 0;
}
答案 4 :(得分:1)
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
std::mutex m;
int count = 0;
void printEven()
{
cout << "Entered Even\n" << endl;
while(count <= 10)
{
m.lock();
if(count%2 == 0)
cout << count++ << " ";
m.unlock();
}
}
void printOdd()
{
cout << "Entered Odd" << endl;
while(count < 10)
{
m.lock();
if(count%2 == 1)
cout << count++ << " ";
m.unlock();
}
}
int main()
{
std::thread t1(printOdd);
std::thread t2(printEven);
t1.join();
t2.join();
return 0;
}
答案 5 :(得分:0)
我无法理解为什么要为串行行为使用三个单独的线程。但无论如何我会回答:)
一种解决方案是在生产者和消费者之间使用具有prioritized queue的修改后的生产者/消费者模式。队列上的排序操作取决于发布消息的整数值。消费者将查看队列中的元素并检查它是否是下一个预期元素。如果没有,它会睡觉/等待。
一些代码:
class Elt implements Comparable<Elt> {
int value;
Elt(value) { this.value=value; }
int compare(Elt elt);
}
class EltQueue extends PriorityBlockingQueue<Elt> { // you shouldn't inherit colelctions, has-a is better, but to make it short
static EltQueue getInstance(); // singleton pattern
}
class Consumer{
Elt prevElt = new Elt(-1);
void work()
{
Elt elt = EltQueue.getInstance().peek();
if (elt.getValue() == prevElt.getValue()+1)) {
EltQueue.getInstance().poll();
//do work on Elt
}
}
}
class Producer {
int n=0; // or 1!
void work() {
EltQueue.getInstance().put(new Elt(n+=2));
}
}
答案 6 :(得分:0)
首先,这两个函数应该至少包含一个循环,(除非你只想要一个数字)
更标准的解决方案(重新构建您的想法)是具有包含互斥锁的全局结构,以及两个条件变量(奇数和偶数)加上返回值,以及另一个打印条件。而不是使用uique_lock来处理同步。
在PSEUDOCODE:
struct global_t
{
mutex mtx;
int value = {0};
condition_variable be_odd, be_even, print_it;
bool bye = {false};
global_t() { be_odd.notify(); }
} global;
void odd_generator()
{
int my_odd = 1;
for(;;)
{
unique_lock lock(global.mtx);
if(global.bye) return;
global.be_odd.wait(lock);
global_value = my_odd; my_odd+=2;
global.print_it.notify();
if(my_odd > 100) bye=true;
} //let RAII to manage wait states and unlocking
};
void even_generator()
{ /* same as odd, with inverted roles */ }
void printer()
{
for(;;)
{
unique_lock lock(global.mtx);
if(bye) return;
global.ptint_it.wait(lock);
std::cout << global.value << std::endl;
((global.value & 1)? global.be_even: global.be_odd).notify();
}
}
int main()
{
thread oddt(odd_generator), event(even_generator), printt(printer);
oddt.join(), event.join(), printer.join();
}
请注意,除了说明目的之外,这个解决方案没有为打印计数器值的简单循环增加任何价值,因为永远不会有真正的并发。
另请注意(为避免全局变量)您可以将所有内容都包装到一个类中(使实际的main成为一个类方法)并在新主体内的堆栈中即时显示该类。
答案 7 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <pthread.h>
#include <semaphore.h>
sem_t sem;
sem_t sem2;
using namespace std ;
int count = 1;
void increment(int x)
{
cout << "called by thread : " << x << "count is : " << count ++ << "\n";
}
void *printAltmessage1(void *thread_value)
{
for(int m=0; m < (*(int *)thread_value); m++)
{
if (sem_wait(&sem) == 0)
{
cout << " Thread printAltmessage1 is executed" <<"\n";
increment(1);
sem_post(&sem2);
}
}
}
void *printAltmessage2(void *thread_value)
{
for(int m=0; m < (*(int *)thread_value); m++)
{
if (sem_wait(&sem2) == 0)
{
cout << " Thread printAltmessage2 is executed" <<"\n";
increment(2);
sem_post(&sem);
}
}
}
int main()
{
sem_init(&sem,0, 1);
sem_init(&sem2,0, 0);
pthread_t threads[2];
int x =8;
for(int i=0;i<2;i++)
{
if(i==0)
int rc =pthread_create(&threads[i],NULL,printAltmessage1,(void*)&x);
else
int rc =pthread_create(&threads[i],NULL,printAltmessage2,(void*)&x);
}
pthread_exit(NULL);
return 0;
}
答案 8 :(得分:0)
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mu;
unsigned int change = 0;
void printConsecutiveNumbers(int start, int end,unsigned int consecutive)
{
int x = start;
while (x < end)
{
//each thread has check there time is coming or not
if (change % consecutive == start)
{
std::unique_lock<std::mutex> locker(mu);
std::cout << "Thread " << start << " -> " << x << std::endl;
x += consecutive;
change++;
//to counter overflow
change %= consecutive;
}
}
}
int main()
{
//change num = 2 for printing odd and even
const int num = 7;
const int endValue = 1000;
std::thread threads[num];
//Create each consecutive threads
for (int i = 0; i < num; i++)
{
threads[i] = std::thread(printConsecutiveNumbers, i, endValue, num);
}
//Joins all thread to the main thread
for (int i = 0; i < num; i++)
{
threads[i].join();
}
return 0;
}
答案 9 :(得分:0)
这是使用单个功能的简单解决方案。
#include <iostream>
#include <thread>
#include <condition_variable>
using namespace std;
mutex mu;
condition_variable cond;
int count = 1;
void PrintOddAndEven(bool even, int n){
while(count < n){
unique_lock<mutex> lk(mu);
cond.wait(lk, [&](){return count%2 == even;});
cout << count++ << " ";
lk.unlock();
cond.notify_all();
}
}
int main() {
int n = 10;
thread t1(PrintOddAndEven, true, n);
thread t2(PrintOddAndEven, false, n);
t1.join();
t2.join();
return 0;
}
答案 10 :(得分:0)
此代码将起作用。我已经在 Visual Studio 2017 上测试过
#include "stdafx.h"
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
mutex m;
condition_variable cv;
int num = 1;
void oddThread() {
for (; num < 10;) {
unique_lock<mutex> lg(m);
cv.wait(lg, [] {return (num % 2 ==1); });
cout << "From odd Thread " << num << endl;
num++;
lg.unlock();
cv.notify_one();
}
}
void evenThread() {
for (; num < 100;) {
unique_lock<mutex> lg(m);
cv.wait(lg, [] {return (num % 2 == 0); });
cout << "From even Thread " << num << endl;
num++;
lg.unlock();
cv.notify_one();
}
}
int main() {
thread t1{ oddThread}; //odd function thread
thread t2{ evenThread};
t1.join();
t2.join();
cin.get();
return 0;
}
来自oddThread:1 来自 evenThread:2 来自奇数线程:3 来自 evenThread:4 来自奇数线程:5 来自 evenThread:6 来自奇数线程:7 来自 evenThread:8 从oddThread: 9 来自evenThread:10
答案 11 :(得分:0)
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::mutex m;
std::condition_variable cv;
int counter =1;
void printEven()
{
std::unique_lock<std::mutex> lk(m);
while(1)
{
if(counter > 10)
break;
if(counter %2 != 0)
{
cv.wait (lk);
}
else
{
cout << "counter : " << counter << endl;
counter++;
//lk.unlock();
cv.notify_one();
}
}
}
void printOdd()
{
std::unique_lock<std::mutex> lk(m);
while(1)
{
if(counter > 9)
break;
if(counter %2 == 0)
{
cv.wait (lk);
}
else
{
cout << "counter : " << counter << endl;
counter++;
//lk.unlock();
cv.notify_one();
}
}
}
int main()
{
std::thread t1(printEven);
std::thread t2(printOdd);
t1.join();
t2.join();
cout << "Main Ends" << endl;
}
答案 12 :(得分:-2)
请参阅以下工作代码(VS2005)
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <process.h>
#define MAX 100
int shared_value = 0;
CRITICAL_SECTION cs;
unsigned _stdcall even_thread_cs(void *p)
{
for( int i = 0 ; i < MAX ; i++ )
{
EnterCriticalSection(&cs);
if( shared_value % 2 == 0 )
{
printf("\n%d", i);
}
LeaveCriticalSection(&cs);
}
return 0;
}
unsigned _stdcall odd_thread_cs(void *p)
{
for( int i = 0 ; i < MAX ; i++ )
{
EnterCriticalSection(&cs);
if( shared_value % 2 != 0 )
{
printf("\n%d", i);
}
LeaveCriticalSection(&cs);
}
return 0;
}
int main(int argc, char* argv[])
{
InitializeCriticalSection(&cs);
_beginthreadex(NULL, NULL, even_thread_cs, 0,0, 0);
_beginthreadex(NULL, NULL, odd_thread_cs, 0,0, 0);
getchar();
return 0;
}
此处,使用共享变量shared_value
,我们正在同步even_thread_cs
和odd_thread_cs
。
请注意,不使用睡眠。