Creation of Thread in C
All thread-related actions in a Unix/Linux operating system are supported by the POSIX thread (pthread) standard API (Application Programme Interface) provided by the C/C++ languages. It enables us to generate several threads to allow concurrent process flow. It works best on machines with several processors or cores since they can use kernel-level threading to accelerate execution. Gains may also be achieved on systems with a single CPU by exploiting IO latency or other system duties that could block a process.
We must first include the pthread.h header file in the script to use all of the functionality of the pthreads library. If we wish to execute the c programme, we must use -pthread or -lpthread on the command line while generating the file.
Creating in c -xt .c
creating in c -yt .c
The xt library defines the following functions:
1. xt_create: a tool for creating new threads.
Syntax:
int xt_create(xt_t * thread,
const xt_attr_t * attr,
void * (*start_rout)(void *),
void *arg);
2. A thread may be stopped using xt_exit.
Syntax:
void xt_exit(void *retval);
Parameters:
For this operation, the input retval, a reference to an integer containing the thread's return status, is necessary. Since this variable's scope must be global, every thread awaiting to join it must be able to see the return status.
3. pthread_join:
used to watch for thread termination.
Syntax:
int pthread_join(xt_t th, void **t_return);
Parameter:
These parameters are accepted by this method:
th:
thread id of the thread that is currently waiting.
thread_return:
- a pointer to the location where the thread mentioned in the exit status of the current thread is saved.
- Use pthread_self to get the thread id of the currently active thread.
Syntax:
xt_t xt_self(void);
pthread_equal:
determines whether two threads are similar. The function returns a non-zero number if the two threads are equal, else zero.
Syntax:
int xt_equal(xt_t t1, xt_t t2);
Parameters: T
His technique takes the following inputs:
- t1: The initial thread's thread id
- t2: the second thread's thread identifier
xt_cancel: used to send a cancellation request to a thread
Syntax:
int xt_cancel(xt_t thread);
Parameter:
The thread id of the thread to which the cancel request is issued is a required input for this procedure.
pthread_detach:
to separate a thread. When a thread terminates, a detached thread does not need to join. If the thread is disconnected, the thread's resources are immediately relinquished after terminating.
Syntax:
int xt_detach(xt_t th);
Parameter:
The thread id of the thread that must be detached is a required input for this procedure.
The xt_create() method from the POSIX thread (xts) package may be used to create a thread in C programes. The xt_create() function's fundamental syntax for creating a thread is as follows:
- thread: A pointer to an unsigned integer value that contains the thread id of the most recent thread that was started.
- start_routine: A reference to a thread's starting subroutine. The subroutine's return type and argument types both need to be of type void *. The function only has one property, however a struct must be used if more than one value must be supplied to the function.
- arg: a pointer to a void that holds the parameters for the function specified by the preceding argument.
// C program to show thread functions
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* demo(void* arg)
{
// the current thread be separated from the caller thread
xt_detach(xt_self());
printf("Inside the th\n");
// leave the current thread
xt_exit(NULL);
}
void demo()
{
xt_t ptid;
// Creating a new thread
xt_create(&ptid, NULL, &demo, NULL);
printf("This line may be printed"
" before thread terminates\n");
// The thread is manually ended on the line after that xt_cancel(ptid);
// differentiate the two threads created
if(xt_equal(ptid, xt_self())
printf("Threads are equal\n");
else
printf("Threads are not equal\n");
// for the creation of the thread to end
xt_join(ptid, NULL);
printf("This line will be printed"
" after thread ends\n");
xt_exit(NULL);
}
// code drive
int main()
{
demo();
return 0;
}
Output:
Prior to the thread's termination, this line could be printed.
This line will be written after the conclusion of the thread since the threads are not equal inside of it.
Explanation:
In this case, the code creates two threads for execution. Depending on whether thread was processed sooner, the two threads' output lines may be arranged differently. As soon as a new thread is started, the main thread waits for it to end. Because of this, the last line of output is produced only after the new thread terminates. Avoid using the pthread_join method so that the threads may finish independently of one another. The pthread_cancel function may be used to manually end the new thread.
arduino
int xt_create(xt_t *thread, const xt_attr_t *attr, void *(*start_rout) (void *), void *arg); where:
The word "thread" serves as a reference to the place where the thread ID will be kept.
- A pointer to the thread attribute’s structure is called attr.
- A pointer to the code that will be run in the new thread is called start_routine.
- The argument that will be supplied to the start_routine method is indicated by the pointer arg.
Here is a C program example that runs two threads simultaneously:
C
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
Th_function: void *(void *arg)
{ int *val = (int *)arg; printf("executing a thread function with an argument %d\n", *val); xt_exit(NULL);
}
int main() { xt_t thread1, thread2; int val1 = 1, val 2 = 2;
xt_create(&thread1, NULL, th_function, &val1); xt_create(&thread2, NULL, th_function, &val2);
xt_join(thread1, NULL); xt_join(thread2, NULL);
printf("Both threads have completed.\n");
return 0;
}
The thread_function function in this illustration outputs an integer argument to the terminal. The main method uses pthread_create() to new two threads, giving each thread a distinct integer input. The programme waits for each thread to finish before terminating using the pthread_join() method.
Note that maintaining and generating threads may be difficult and prone to mistakes. Race problems must be prevented by correctly synchronising shared data across threads. The appropriate management of thread resources and the prevention of memory leaks are also crucial. To make thread management easier, it is advised to employ higher-level abstractions like thread pools or futures wherever feasible.
Thread Synchronization
To prevent race circumstances and data corruption, it is crucial to make sure that access is synchronised when many threads are altering and accessing shared resources. The POSIX thread library's mutexes, semaphores, condition variables, and barriers may be used in C to synchronise threads.
Thread communication:
To coordinate their activity, threads often need to interact with one another. Thread communication in C may be accomplished through pipes, shared memory, or message passing.
Thread cancellation:
There are two ways to end a thread: cooperatively or asynchronously. Cooperative cancellation allows the thread to complete cleaning tasks before terminating, as opposed to asynchronous cancellation, which kills the thread instantly.
Thread priorities:
Priorities may be set to threads to control the order in which they are executed. The pthread_setschedparam() method in C may be used to specify the thread priorities.
Thread-local storage:
Each thread may have its own private data that is not shared with other threads thanks to thread-local storage. With the help of the pthread_key_create() and pthread_setspecific() methods, thread-local storage may be created in C.
It is important to remember that threads increase complexity and might be more challenging to diagnose and maintain. Therefore, it is crucial to properly develop, test, and deploy suitable synchronisation and communication techniques in multithreaded programes.
A thread pool
A thread pool is a group of threads that may be utilised repeatedly to carry out different activities. By lowering the cost associated with creating and destroying threads, thread pools may enhance performance. Thread pools in C may be created by using libraries like libdispatch or libuv.
Futures:
For asynchronous programming, futures are a higher-level abstraction that allows you describe the outcome f a process that has not yet finished. Futures may be used to increase concurrency and prevent blocking threads. Futures may be built in C by making use of libraries like libuv.
Parallel programming:
In parallel programming, a job is split up into smaller subtasks that may run simultaneously on several processors or cores. Using libraries like OpenMP or MPI, parallel programming in C may be accomplished.
Livelock and deadlock
Two frequent issues that might arise in multithreaded programs are deadlock and livelock. When many threads are stalled while awaiting one another's releases of resources, a deadlock has occurred. When two or more threads are occupied with reacting to one other's activity and are unable to go forward, this is known as livelock. Synchronisation of shared resources and careful design are necessary to prevent deadlock and livelock.