这是家庭作业
必须按顺序打印一个字符串(给定为输入)由多个线程按顺序打印(作为输入的大小)1,2,3,1,2,3,1,2(线程数给出为输入)。
一个线程在创建时执行此打印功能,我希望它在所有其他线程之后重做它。我面临两个问题:
1.线程不按固定顺序打印(我的给出1,3,2,4见输出)
2.线程需要重新打印,直到整个字符串耗尽。
这就是我试过的......
#include<iostream>
#include<mutex>
#include<thread>
#include<string>
#include<vector>
#include<condition_variable>
#include<chrono>
using namespace std;
class circularPrint{
public:
int pos;
string message;
int nCharsPerPrint;
mutex mu;
condition_variable cv;
circularPrint(){
pos=0;
}
void shared_print(int threadID){
unique_lock<mutex> locker(mu);
if(pos+nCharsPerPrint<message.size())
cout<<"Thread"<<threadID<<" : "<<message.substr(pos,nCharsPerPrint)<<endl;
else if(pos<message.size())
cout<<"Thread"<<threadID<<" : "<<message.substr(pos)<<endl;
pos+=nCharsPerPrint;
}
};
void f(circularPrint &obj,int threadID){
obj.shared_print(threadID);
}
int main(){
circularPrint obj;
cout<<"\nMessage : ";
cin>>obj.message;
cout<<"\nChars : ";
cin>>obj.nCharsPerPrint;
int nthreads;
cout<<"\nThreads : ";
cin>>nthreads;
vector<thread> threads;
for(int count=1;count<=nthreads;++count)
{
threads.push_back(thread(f,ref(obj),count));
}
for(int count=0;count<nthreads;++count)
{
if(threads[count].joinable())
threads[count].join();
}
return 0;
}
答案 0 :(得分:1)
为什么要多线程一次只能执行一次的方法?
无论如何,下面这样的话?请注意take
和print
使用不同的锁,并且输出有可能不按预期顺序显示(因此,上面的原因问题)。
#include <iostream>
#include <mutex>
#include <thread>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class circularPrint
{
public:
int pos;
string message;
int nCharsPerPrint;
mutex takeLock;
mutex printLock;
circularPrint() {
pos = 0;
}
string take(int count) {
lock_guard<mutex> locker(takeLock);
count = std::min(count, (int)message.size() - pos);
string substring = message.substr(pos, count);
pos += count;
return substring;
}
void print(int threadID, string& message) {
lock_guard<mutex> locker(printLock);
cout << "Thread" << threadID << " : " << message << endl;
}
void loop(int threadID) {
string message;
while((message = take(nCharsPerPrint)).size() > 0) {
print(threadID, message);
}
}
};
void f(circularPrint &obj, int threadID)
{
obj.loop(threadID);
}
int main()
{
circularPrint obj;
//cout << "\nMessage : ";
//cin >> obj.message;
//cout << "\nChars : ";
//cin >> obj.nCharsPerPrint;
int nthreads;
//cout << "\nThreads : ";
//cin >> nthreads;
nthreads = 4;
obj.message = "123456789012345";
obj.nCharsPerPrint = 2;
vector<thread> threads;
for (int count = 1; count <= nthreads; ++count)
threads.push_back(thread(f, ref(obj), count));
for (int count = 0; count < nthreads; ++count) {
if (threads[count].joinable())
threads[count].join();
}
return 0;
}
答案 1 :(得分:0)
你需要线程间同步,每个线程做一个循环“打印,向下一个发送消息,等待消息(从最后一个线程)”。
您可以使用信号量,事件,消息或类似的东西。
东西:
#include <string>
#include <iostream>
#include <condition_variable>
#include <thread>
#include <unistd.h>
using namespace std;
// Parameters passed to a thread.
struct ThreadParameters {
string message; // to print.
volatile bool *exit; // set when the thread should exit.
condition_variable* input; // condition to wait before printing.
condition_variable* output; // condition to set after printing.
};
class CircularPrint {
public:
CircularPrint(int nb_threads) {
nb_threads_ = nb_threads;
condition_variables_ = new condition_variable[nb_threads];
thread_parameters_ = new ThreadParameters[nb_threads];
threads_ = new thread*[nb_threads];
exit_ = false;
for (int i = 0; i < nb_threads; ++i) {
thread_parameters_[i].message = to_string(i + 1);
thread_parameters_[i].exit = &exit_;
// Wait 'your' condition
thread_parameters_[i].input = &condition_variables_[i];
// Then set next one (of first one if you are the last).
thread_parameters_[i].output =
&condition_variables_[(i + 1) % nb_threads];
threads_[i] = new thread(Thread, &thread_parameters_[i]);
}
// Start the dance, free the first thread.
condition_variables_[0].notify_all();
}
~CircularPrint() {
// Ask threads to exit.
exit_ = true;
// Wait for all threads to end.
for (int i = 0; i < nb_threads_; ++i) {
threads_[i]->join();
delete threads_[i];
}
delete[] condition_variables_;
delete[] thread_parameters_;
delete[] threads_;
}
static void Thread(ThreadParameters* params) {
for (;;) {
if (*params->exit) {
return;
}
{
// Wait the mutex. We don't really care, by condition variables
// need a mutex.
// Though the mutex will be useful for the real assignement.
unique_lock<mutex> lock(mutex_);
// Wait for the input condition variable (frees the mutex before waiting).
params->input->wait(lock);
}
cout << params->message << endl;
// Free next thread.
params->output->notify_all();
}
}
private:
int nb_threads_;
condition_variable* condition_variables_;
ThreadParameters* thread_parameters_;
thread** threads_;
bool exit_;
static mutex mutex_;
};
mutex CircularPrint::mutex_;
int main() {
CircularPrint printer(10);
sleep(3);
return 0;
}
使用vector<shared_ptr<...>>
会比仅使用数组更优雅,但这有效:
g++ -std=c++11 -o test test.cc -pthread -Wl,--no-as-needed
./test
答案 2 :(得分:0)
目前每个线程在打印一条消息后退出 - 但是您需要的消息多于线程,因此每个线程需要执行多条消息。
如何在当前锁定的部分周围设置无限循环,并在没有剩余字符打印时爆发?
(然后你可能会发现第一个线程完成了所有工作;你可以通过在锁定部分之外放置零长度睡眠,或者通过让所有线程等待某个单个信号启动,或者只是活着来破解它用它。)
编辑:没有意识到你想要将工作分配给特定的线程(这通常是一个非常糟糕的主意)。但是如果每个线程知道它的ID,以及它有多少,它可以找出它应该打印的字符。然后它所要做的就是等到所有前面的字符都被打印出来(它可以用pos
告诉它),做它的工作,然后重复直到它没有工作要做并退出。
唯一棘手的问题是等待前面的工作完成。你可以通过忙碌的等待(糟糕),忙碌的等待(也是坏的)或条件变量(更好)来做到这一点。