Recently in the study of multi-threading, the topic originates from Mr. Morewindows's "second Kill multithreading First" (http://blog.csdn.net/morewindows/article/details/7392749)
Title Excerpt:
Question Fifth (Google interview questions)
There are four threads of 1, 2, 3, 4. The function of thread 1 is output 1, the function of thread 2 is output 2, etc... There are now four file ABCD. The initial is empty. Now you want four files to appear in the following format:
A:1 2 3 4 1 2 ....
B:2 3 4 1 2 3 ....
C:3 4 1 2 3 4 ....
D:4 1 2 3 4 1 ....
Please design the program.
The code is implemented as follows:
1#include <iostream>2#include <string>3#include <thread>4#include"Semaphore.h"5 6constexpr unsigned max_count =Ten;7constexpr unsigned max_thread =4;8 9Unsigned getNext (unsigned current,BOOLorder) {Ten if(order) { OneUnsigned next = current +1; A returnNext% Max_thread;// //Positive Order -}Else { -Unsigned next = current-1; the returnNext% Max_thread;//reverse Order - } - } - + classFile - { + Public: AFile (ConstSTD::string& name ="0") at : M_name (name) -, M_buffer (Max_count,'0') -, M_pos (0){ - - } - in voidWriteCharc) { -m_buffer.at (m_pos++) =C; to } + -STD::stringGetName ()Const { the returnM_name; * } $STD::stringGetData ()Const {Panax Notoginseng returnM_buffer; - } the Private: +STD::stringM_name; ASTD::stringM_buffer; the size_t M_pos; + }; - $Semaphore T1 (1), T2 (1), T3 (1), T4 (1); $semaphore* Semaphorearray[max_thread] = {&t1, &t2, &T3, &T4}; -File Files[max_thread] = {file ("A"), File ("B"), File ("C"), File ("D") }; -unsigned Currentfile[max_thread] = {0,1,2,3};//the file ID that each thread should currently write to the - voidwrite (unsigned threadId) {Wuyi Const Charc ='1'+threadId; theauto& FID =Currentfile[threadid]; - //Auto FID = threadId; WuAuto Nextthreadid = GetNext (ThreadId,true);//Positive Order -unsigned count =0; About while(Max_count! =count) { $Semaphorearray[threadid]->wait (); - //Write a file - Files[fid].write (c); - //Pass the file to the next thread. ASemaphorearray[nextthreadid]->signal (); + //update the file ID to be written theFID = GetNext (FID,false);//Reverse -++count; $ } the } the the the intMain () { -Std::cout <<"Hello"<<Std::endl; in the //Create thread the Std::thread Threads[max_thread]; About for(Unsigned i =0; I! = Max_thread; ++i) { theThreads[i] =Std::thread (write, i); the } the + //Join - for(auto&thread:threads) { the Thread.Join ();Bayi } the the //Output - for(Constauto&file:files) { -Std::cout << file.getname () <<": "<< File.getdata () <<Std::endl; the } the theStd::cout <<"Bye"<<Std::endl; the return 0; -}
Where Semaphore.h's code is shown in: http://www.cnblogs.com/waterfall/p/7966116.html
Operation Result:
Code parsing:
First of all, this code with the file class simulation files written to facilitate print debugging. The Void File::write (char c) method appends the character C to the end of the file.
As you can see from the topic, when a file (such as file a) is written by thread 1, it needs to be written by the next thread, thread 2. So there will be a:1 2 3 4 1 ... The B,c,d file is the same, except that the initial write thread is different.
In the Code type utilization:
0 1 2 3 // the file ID that each thread should currently write to
Specifies which file each thread writes to initially. If you do not want to configure, you can also use ThreadID as the file ID of the thread's initial write (the one commented out in the Write function), they are just equal.
The number of times the thread can write writes is represented in the code with semaphores. The Write function automatically calculates the next file to be written after a file is written. Order for a,d,c,b,a ...., reverse.
Semaphore T1 (1), T2 (1), T3 (1), T4 (1);//For setting the semaphore Semaphore* Semaphorearray[max_thread] = {&t1, &t2, &t3, &T4}; Putting an array is just for the convenience of calling
If you just set the semaphore for thread 1 to 1, the others are set to 0. The health of a thread can be seen as:
Step1: Thread 1 semaphore 1 a->d thread 2 semaphore 0 B blocking thread 3 semaphore 0 C blocking thread 4 semaphore 0 D blocking
Step2: Thread 1 semaphore 0 D block thread 2 semaphore 1 b->a thread 3 semaphore 0 C block thread 4 Semaphore 0 D block
Step3: Thread 1 semaphore 0 D blocking thread 2 semaphore 0 A blocking thread 3 semaphore 1 c->b thread 4 semaphore 0 D block
STEP4: Thread 1 semaphore 0 D blocking thread 2 semaphore 0 A blocking thread 3 semaphore 0 B blocking thread 4 semaphore 1 d->c
The first run ends: Thread 1 writes 1 in file A, thread 2 writes 2 in file B, thread 3 writes 3 in file C, and thread 4 writes 4 in file D.
Then the second round begins: Thread 1 writes 1 in file D, thread 2 writes 2 in file a ...
And so on, the equivalent of only 1 threads at the same time are working. Each time the thread is working, the character is written to the file that it is currently writing to, and the next file to be written is computed.
There is clearly no conflict in this situation.
If you set the initial semaphore of thread 1 to 2:
Step1: Thread 1 semaphore 2 a->d thread 2 semaphore 0 B blocking thread 3 semaphore 0 C blocking thread 4 semaphore 0 D blocking
Step2: Thread 1 semaphore 1 d->c thread 1 semaphore 1 b->a thread 3 semaphore 0 C block thread 4 Semaphore 0 D block
You can see that the character 1 is written in file D and an error occurs. The reason is that file D is currently expecting to be written by thread 4 and is not ready before 4 writes. It is wrong to write to any other thread at this time.
If the initial semaphore of thread 1 and thread 4 is assumed to be 1, the other is 0. and assume that thread 4 runs first
step1.1: Thread 1 semaphore 1 A ready thread 2 semaphore 0 B blocking thread 3 semaphore 0 C blocking thread 4 semaphore 1 d->c
step1.2: Thread 1 semaphore 2 a->d thread 2 semaphore 0 B blocking thread 3 semaphore 0 C blocking thread 4 semaphore 0 C blocking
step2.1: Thread 1 semaphore 1 d->c thread 1 semaphore 1 b->a thread 3 semaphore 0 C block thread 4 Semaphore 0 D block
File d is first written to the character 4 by thread 4, followed by thread 1 to write character 1 to meet the requirements. (The sequence of D should be: 4 1 2 3 4 ...)
That is, the increase in the semaphore of thread 1 is based on the previous thread having finished writing the file. At this point the file is in a ready state and can be used by the next thread to pass the file to the next thread.
So in the final code, set the initial semaphore for each thread to 1. To meet the requirements of the topic. Even if any thread is blocked in execution (sleep emulation is available), it does not affect other threads running.
Suppose a long sleep is performed in thread 1. The possible operating conditions are as follows
STEP0: Thread 1 semaphore 1 A Ready thread 2 semaphore 1 B ready thread 3 semaphore 1 C Ready thread 4 semaphore 1 D ready
After some time ...
Step1: Thread 1 semaphore 4 a Ready thread 2 semaphore 0 A blocking thread 3 semaphore 0 A blocking thread 4 semaphore 0 A blocking
All threads are waiting for the data to be written to file a. However, only thread 1 writes the character 1 in file A before releasing the signal, B to continue writing. And then the c,d. There is still no conflict. File A also satisfies the 1,2,3,4 character order.
Other:
Many of the online search code, at the same time only allow one thread to write the file, or through the count, the end of the round before the next write. This code really implements the parallelism between threads. Wait only if there is no file to write.
Thank you.
(Google interview) has four threads 1, 2, 3, 4 synchronously write data ... C++11 implementation