Is it possible for two threads to use a single function "ThreadProc" as its thread procedure when CreateThread() is used?
HANDLE thread1= CreateThread( NULL, //Choose default security
0, //Default stack size
(LPTHREAD_START_ROUTINE)&ThreadProc,
//Routine to execute. I want this routine to be different each time as I want each thread to perform a different functionality.
(LPVOID) &i, //Thread parameter
0, //Immediately run the thread
&dwThreadId //Thread Id
)
HANDLE thread2= CreateThread( NULL, //Choose default security
0, //Default stack size
(LPTHREAD_START_ROUTINE)&ThreadProc,
//Routine to execute. I want this routine to be different each time as I want each thread to perform a different functionality.
(LPVOID) &i, //Thread parameter
0, //Immediately run the thread
&dwThreadId //Thread Id
)
Would the above code create two threads each with same functionality(since thread procedure for both of the threads is same.) Am I doing it correctly?
If it is possible then would there be any synchronization issues since both threads are using same Thread Procedure.
Please help me with this. I am really confused and could not find anything over the internet.
It is fine to use the same function as a thread entry point for multiple threads.
However, from the posted code the address of i is being passed to both threads. If either thread modifies this memory and the other reads then there is a race condition on i. Without seeing the declaration of i it is probably a local variable. This is dangerous as the threads require that i exist for their lifetime. If i does not the threads will have a dangling pointer. It is common practice to dynamically allocate thread arguments and have each thread free its arguments.
Yes, it is very well possible to have multiple (concurrent) threads that start with the same entry point.
Apart from the fact that the OS/threading library specifies the signature and calls it, there is nothing special about a thread entry point function. It can be used to start off multiple threads with the same caveats as for calling any other function from multiple threads: you need synchronization to access non-atomic shared variables.
Each thread uses its own stack area, but that gets allocated by the OS before the Thread Procedure get invoked, so by the time the Thread Procedure gets called all the special actions that are needed to create and start a new thread have already taken place.
Whether the threads are using the same code or not is irrelevant. It has no effect whatsoever on synchronization. It behaves precisely the same as if they were different functions. The issues with potential races is the same.
You probably don't want to pass both threads the same pointers. That will likely lead to data races. (Though we'd have to see the code to know for sure.)
Your code is right. There is NOT any synchronization issues between both threads. If they need synchronization, it maybe because they are change the same global variable, not because they use the same thread Procedure.
Related
I have a question in regards to creating threads.
Specifically I want to know the difference between looping through thread[i]
and not looping but recalling pthread_create
For Example
A. Initializes 5 threads
for(i=0,i<5;i++){
pthread_create(&t[i],NULL,&routine,NULL);
}
B. Incoming clients connecting to a server
while(true){
client_connects_to_server = accept(sock, (struct sockaddr *)&server,
(socklen_t*)&server_len)
pthread_create(&t,NULL,&routine,NULL); //no iteration
}
Is the proper method of creating threads for incoming clients, to keep track of the connections already made, maybe something like this ?
pthread_create(&t[connections_made+1],&routine,NULL)
My concern is not being able to handle concurrent pthreads if option B is terminating threads or "re-writing" client connections.
Here is an example where no iteration is done
https://gist.github.com/oleksiiBobko/43d33b3c25c03bcc9b2b
Why is this correct ?
Contrary to your apparent assertion, both your examples call pthread_create() inside loops. In example A, it is a for loop that will iterate a known number of times, whereas in example B, it is a while loop that will iterate an unbounded number of times. I guess the known number vs unbounded number is what you mean by "static" and "dynamic", but that is not a conventional usage of those terms.
In any event, pthread_create() does what it is documented to do. Like any other function, it does not know anything about the context from which it is called other than the arguments passed to it. It can fail, but that's not influenced by looping by the caller, at least not directly. When pthread_create() succeeds, it creates and starts a new thread, which runs until the top-level call to its thread function returns, pthread_exit() is called by thread, the thread is canceled, or the process terminates.
The main significant difference between your two examples is that A keeps all the thread IDs by recording them in different elements of an array, whereas B overwrites the previous thread ID each time it creates a new thread. But the thread IDs are not the threads themselves. If you lose the ID of a thread then you can no longer join it, among other things, but that doesn't affect the thread's operation, including its interactions with memory, with files, or with synchronization objects such as semaphores. In this regard, example B is more suited for a thread function that will detach the thread in which it is called, so that the joining issue is moot. Example A's careful preservation of all the thread IDs would pointless for threads that detach themselves, but necessary if the threads need to be joined later.
I'm writing code to save text to a binary file, which includes a function to auto-save text to the binary file, as well as a function to print from the binary file, and I need to incorporate pthread locks and join. We were given
pthread_mutext_t mutex;
pthread_t autosavethread;
as global variables, although the instructor didn't talk about what pthread or mutex actually do, so I'm confused about that.
Also, I understand that I need to use locks whenever shared variables are changed or read (in my case it would be the binary file). But at the end of the file I am supposed to use pthread_join, and I don't know what it does or what arguments are supposed to be used in it. I'm guessing mutex and autosavethread are supposed to be closed, or something along the lines of that, but I don't know how to write it. Can anyone help better my understanding?
There are two types of pthread - joinable thread & detached thread.
If you want to let a thread just take a task and go away once the task is done, you need the detached thread;
If you want to have the communication with the created thread when that thread is done with the assigned job, you have to use joinable thread. Basically it's needed when the parent & its created thread need to communicate after the thread is done.
It's very to google what exactly you need to call the pthread APIs and what can be communicated.
But one thing i want to mention here is, for the joinable thread, you have to explicitly call the pthread_join against the created thread. Otherwise, there will be serious memory leaks. When the joinable thread completes its task, the thread seems to exit (On linux, you can check the /proc/PID/task/ folder and once the thread completes, the entry under it will go away), but the resource allocated for this joinable thread, i.e. stack, is still there in the process memory space. As more and more joinable threads created and completing their tasks, the stacks for each thread are just left in process space, unless you explicitly call the pthread_join. Hope that helps, even a bit
Does the function "pthread_create" start the thread (starts executing its function), or does it just creates it and make it wait for the right moment to start?
pthread_create creates the thread (by using clone syscall internally), and return the tid (thread id, like pid). So, at the time when pthread_create returns, the new thread is at least created. But there are no guaranties when it will be started.
From the Man:
http://man7.org/linux/man-pages/man3/pthread_create.3.html
Unless real-time scheduling policies
are being employed, after a call to pthread_create(), it is
indeterminate which thread—the caller or the new thread—will next
execute.
POSIX has the similar comment in the informative description of pthread_create http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_create.html
There is no requirement on the implementation that the ID of the created thread be available before the newly created thread starts executing.
There is also long "Rationale" why pthread_create is single step process without separate thread creation and start_execution (as it was in good old Java epoch):
A suggested alternative to pthread_create() would be to define two separate operations: create and start. Some applications would find such behavior more natural. Ada, in particular, separates the "creation" of a task from its "activation".
Splitting the operation was rejected by the standard developers for many reasons:
The number of calls required to start a thread would increase from one to two and thus place an additional burden on applications that do not require the additional synchronization. The second call, however, could be avoided by the additional complication of a start-up state attribute.
An extra state would be introduced: "created but not started". This would require the standard to specify the behavior of the thread operations when the target has not yet started executing.
For those applications that require such behavior, it is possible to simulate the two separate steps with the facilities that are currently provided. The start_routine() can synchronize by waiting on a condition variable that is signaled by the start operation.
You may use RT scheduling; or just add some synchronization in the created thread to get exact information about it's execution. It can be also useful in some cases to manually bind the thread to specific CPU core using pthread_setaffinity_np
It creates the thread and enters the ready queue. When it gets its slice from the scheduler, it starts to run.
How early it gets to run will depend upon thread's priority, no of threads it is competing against among other factors.
The first argument of pthread_create() is a thread object which is used to identify the newly-created thread. However, I'm not sure I completely understand the implacations of this.
For instance, I am writing a simple chat server and I plan on using threads. Threads will be coming and going at all times, so keeping track of thread objects could be complicated. However, I don't think I should need to identify individual threads. Could I simply use the same thread object for the first argument of pthread_create() over and over again, or are there other ramifications for this?
If you throw away the thread identifiers by overwriting the same variable with the ID of each thread you create, you'll not be able to use pthread_join() to collect the exit status of threads. So, you may as well make the threads detached (non-joinable) when you call pthread_create().
If you don't make the threads detached, exiting threads will continue to use some resource, so continually creating attached (non-detached) threads that exit will use up system resources — a memory leak.
Read the manual at http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_create.html
According to it:
"Upon successful completion, pthread_create() shall store the ID of the created thread in the location referenced by thread."
I think pthread_create just overwrites the value in the first argument. It does not read it, doesn't care what is inside it. So you can get a new thread from pthread_create, but you can't make it reuse an existing thread. If you would like to reuse your threads, that is more complicated.
I have a method which is is meant to write information into a struct. I want to make it run as a thread.
If I call it by itself, as childWriter((void*) &sa) it works.
If I call pthread_create(&writerChild, NULL, childWriter, (void*) &sa), it no longer works. It doesn't write to the shared object.
This is driving me mad. Why isn't it working, and how do I make it work?
What makes you so sure that the code doesn't execute? Note that if you do something like:
int main(int argc, char* argv[])
{
pthread_create(....);
return 0;
}
In the above, the program will quit right away, because the program exits as soon as the main thread has terminated. You need to "join" the thread (using pthread_join), in order to wait for the thread to have terminated. Note that spawning a thread and then joining it is actually worse than simply running the content that the thread would run (since spawning and then joining a thread is equivalent to running the content serially, plus it adds the overhead of the spawn/join). If you intend to multithread things, typically one spawns multiple threads and then either detaches them or joins them later.
Also, you should be cautious about sharing data between threads that can be modified; any object that is read from multiple threads and is modified in even one thread requires explicit locking around access to that object. Otherwise, you can end up with all sorts of garbage and corruption.
Short version:
Use pthread_join() before you read the data from the struct:
pthread_create(&writerChild, NULL, childWriter, (void*) &sa);
//if necessary, do some other tasks, not related to the struct, here
pthread_join(writerChild,NULL);
//now, you may read from the struct
If you are creating the thread in one function, & reading the struct in another function, simply shift the pthread_join statement to the latter, just before you read from the struct. (Also make sure that the pthread_t variable writerChild is visible in the reading function's scope)
Long version:
Threads are generally used in programs where tasks can be parallelized. I suppose your intention here is to read the data written to the struct after the childWriter function writes to it.
When you call your function in a single-threaded process, via:
childWriter((void*) &sa);
the thread / process shifts to execute the instructions that are part of your function. Only when the function returns, does the execution control return to the point from which you called the function. Hence, you can be sure that childWriter has completed its execution, before you begin to read from your struct in the calling function.
When you create a new thread, via:
pthread_create(&writerChild, NULL, childWriter, (void*) &sa);
the thread runs in parallel with your "main" thread. There is no guarantee that the newly created thread will get a chance to execute before the next instructions in the main thread get exectued, leave alone the possibilty that the childWriter thread function completes its execution prior to reading the struct.
Hence, you need to wait for the thread to complete its execution. This can be accomplished using pthread_join().