I wanted to calculate the time between creating a thread and taking control by it, then compare this time for normal and suspended threads. But the results are quite chaotic.
So, my question is: Does it really makes sense? I think that instant resuming doesn't have a visible effect on the result.
#include <iostream>
#include <windows.h>
using namespace std;
DWORDLONG freq;
DWORD WINAPI startThread(LPVOID lpParam) {
DWORDLONG c_beg = *((DWORDLONG*)lpParam);
DWORDLONG c_end;
QueryPerformanceCounter((LARGE_INTEGER*)&c_end);
cout << (double(c_end - c_beg)) / (freq) << endl;
return 0;
}
int main()
{
DWORDLONG c_beg;
HANDLE iThread, sThread;
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
cout << "instant" << endl;
for (int i = 0; i < 10; i++) {
QueryPerformanceCounter((LARGE_INTEGER*)&c_beg);
iThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)startThread, (LPVOID*)&c_beg, 0, NULL);
WaitForSingleObject(iThread, INFINITE);
}
cout << "suspended" << endl;
for (int i = 0; i < 10; i++) {
QueryPerformanceCounter((LARGE_INTEGER*)&c_beg);
sThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)startThread, (LPVOID*)&c_beg, CREATE_SUSPENDED, NULL);
ResumeThread(sThread);
WaitForSingleObject(sThread, INFINITE);
}
CloseHandle(iThread);
CloseHandle(sThread);
return 0;
}
Related
So I was making an application using C++ Console, with multi threading as below, then I got an error 0x0000005.
The first time it run it was working as usual. Can anyone help me with this problem?
I am using Code::Blocks IDE with Borland C++ 5.5, and I am planning to make this into Borland C++ 5.02
#include <windows.h>
#include <stdio.h>
#include <dos.h>
#include <iostream.h>
#include <conio.h>
void linesmov(int mseconds, int y);
void linesmov(int mseconds, int y)
{
int i=0;
while (true)
{
i=i+1;
// Or system("cls"); If you may...
gotoxy(i,y);
cout << "____||____||____";
gotoxy(i-1,y);
cout << " ";
Sleep(mseconds);
if (i>115)
{
i=0;
for(int o = 0; o < 100; o++)
{
gotoxy(0,y);
cout << " ";
}
}
}
}
DWORD WINAPI mythread1(LPVOID lpParameter)
{
printf("Thread inside %d \n", GetCurrentThreadId());
linesmov(5,10);
return 0;
}
DWORD WINAPI mythread2(LPVOID lpParameter)
{
printf("Thread inside %d \n", GetCurrentThreadId());
linesmov(30,15);
return 0;
}
int main(int argc, char* argv[])
{
HANDLE myhandle1;
DWORD mythreadid1;
HANDLE myhandle2;
DWORD mythreadid2;
myhandle1 = CreateThread(0,0,mythread1,0,0,&mythreadid1);
myhandle2 = CreateThread(0,0,mythread2,0,0,&mythreadid2);
printf("Thread after %d \n", mythreadid1);
getchar();
return 0;
}
All of these solutions in comments including mine are definitely not the way how it should be done. The main problem is lack of synchronization between threads and lack of processing their termination. Also, every function should be checked for thread-safe compatibility or should be wrapped to match it.
Considering std::cout since c++11 we have some data race guarantees:
Concurrent access to a synchronized (§27.5.3.4) standard iostream
object’s formatted and unformatted input (§27.7.2.1) and output
(§27.7.3.1) functions or a standard C stream by multiple threads shall
not result in a data race (§1.10). [ Note: Users must still
synchronize concurrent use of these objects and streams by multiple
threads if they wish to avoid interleaved characters. — end note ]
So lask of synchronization primitives is oblivious according to this note.
Considering processing of thread termination.
HANDLE threadH = CreateThread(...);
...
TerminateThread(threadH, 0); // Terminates a thread.
WaitForSingleObject(threadH, INFINITE); // Waits until the specified object is in the signaled state or the time-out interval elapses.
CloseHandle(threadH); // Closes an open object handle.
TerminateThread(), but be aware of this solution, because ..
WaitForSingleObject()
And this is only first steps to thread-safe way.
I would like to recommend C++ Concurrency in Action: Practical Multithreading by Anthony Williams for further reading.
Rude solution for synchronized output
#include <Windows.h>
#include <iostream>
#include <mutex>
std::mutex _mtx; // global mutex
bool online = true; // or condition_variable
void gotoxy(int x, int y)
{
COORD c = { x, y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
void linesmov(int mseconds, int y) {
int i = 0;
while (online) {
i = i + 1;
// Or system("cls"); If you may...
_mtx.lock(); // <- sync here
gotoxy(i, y);
std::cout << "____||____||____"; gotoxy(i - 1, y);
std::cout << " ";
_mtx.unlock();
Sleep(mseconds);
if (i > 75)
{
i = 0;
for (int o = 0; o < 60; o++)
{
_mtx.lock(); // <- sync here
gotoxy(0, y);
std::cout << " ";
_mtx.unlock();
}
}
}
}
DWORD WINAPI mythread1(LPVOID lpParameter)
{
std::cout << "Thread 1" << GetCurrentThreadId() << std::endl;
linesmov(5, 10);
return 0;
}
DWORD WINAPI mythread2(LPVOID lpParameter)
{
std::cout << "Thread 2" << GetCurrentThreadId() << std::endl;
linesmov(30, 15);
return 0;
}
int main(int argc, char* argv[])
{
DWORD mythreadid1;
DWORD mythreadid2;
HANDLE myhandle1 = CreateThread(0, 0, mythread1, 0, 0, &mythreadid1);
HANDLE myhandle2 = CreateThread(0, 0, mythread2, 0, 0, &mythreadid2);
std::cout << "Base thread: " << GetCurrentThreadId() << std::endl;
getchar();
online = false;
WaitForSingleObject(myhandle1, INFINITE);
WaitForSingleObject(myhandle2, INFINITE);
CloseHandle(myhandle1);
CloseHandle(myhandle2);
return 0;
}
a) Both gotoxy not outputting via std::cout are not thread safe /synchronized. You need process-wide mutex to synchronize that
b) exception is likely due to fact that you do not use WaitForMultipleObjects in main to wait for threads to finish. Depending on hardware and optimization main may exit before threads finish their work.
I'm trying to start a couple of threads, each on it's own core (4 cores -> 4 threads e.g.).
Pin the threads to their cores looks like:
pthread_t thread_objs[cpu_count];
pthread_attr_t attr;
cpu_set_t cpus;
pthread_attr_init(&attr);
for (unsigned int t = 0; t < cpu_count; t++) {
pthread_t new_thread;
CPU_ZERO(&cpus);
CPU_SET(t, &cpus);
if(pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpus)) {
std::cerr << "fatal: could not set affinity" << std::endl;
return 1;
}
if(pthread_create(&thread_objs[t], &attr, start_routine, NULL)) {
std::cerr << "fatal: thread creation failed" << std::endl;
return 1;
}
}
for (unsigned int t = 0; t < cpu_count; t++) {
pthread_join(thread_objs[t], NULL);
}
Ẁhile testing, I figured out that the first call of pthread_attr_setaffinity_np never returns. I waited several hours, but nothing happened.
Used glibc is ldd (Ubuntu GLIBC 2.23-0ubuntu9) 2.23.
Below I post my code (basically the same as in the question), it works for me on Ubuntu (actually Goobuntu) 14 with a 12-core machine. Reduce nr of CPUs variable to get it to run on a machine with fewer cores.
#include <pthread.h>
#include <unistd.h>
#include <iostream>
using std::cerr;
using std::cout;
const int cpu_count = 12;
pthread_t thread_objs[cpu_count];
pthread_attr_t attr;
cpu_set_t cpus;
void* start_routine(void*)
{
sleep(2);
return 0;
}
int main()
{
pthread_attr_init(&attr);
for (unsigned int t = 0; t < cpu_count; t++) {
pthread_t new_thread;
CPU_ZERO(&cpus);
CPU_SET(t, &cpus);
cout << "Nr of set cpus in set: " << CPU_COUNT(&cpus) << '\n';
if(pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpus)) {
std::cerr << "fatal: could not set affinity" << std::endl;
return 1;
}
if(pthread_create(&thread_objs[t], &attr, start_routine, NULL)) {
std::cerr << "fatal: thread creation failed" << std::endl;
return 1;
}
}
for (unsigned int t = 0; t < cpu_count; t++) {
pthread_join(thread_objs[t], NULL);
}
cout << "Joined all threads, ending!\n";
}
I am working on a homework assignment and I've hit a wall. The assignment is to use 2 threads with controlling mutex to reduce a number x over a loop of 5 iterations.
The first thread does x=x-5
The second thread does x = x/5
The proper result should reduce x to 5 from 19530 over 5 iterations alternating between thread1 and thread2 at each iteration.
I have the following result as of now:
Thread1: x = 19525
Thread1: x = 19520
Thread1: x = 19515
Thread1: x = 19510
Thread1: x = 19505
From above it is clear that my second thread is not only not doing it's job but it's not doing anything at all.
Below is my code, it is written in C++ but the style is using the tools we learned in class which is how one would do it in C but it should work the same either way.
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
using namespace std;
void *first(void *);
void *second(void *);
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
int x = 19530; // global var that is being manipulated
int i = 1; // counter for the loops
int main() {
int t1, t2;
pthread_t thread1, thread2;
if((t1 = pthread_create( &thread1, NULL, first, NULL))) {
printf("Thread creation failed: %d\n", t2);
}
if((t2 = pthread_create( &thread2, NULL, second, NULL))) {
printf("Thread creation failed: %d\n", t2);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return(0);
}
void *first(void *){ // function for thread1
for(; i <=5; i++){
pthread_mutex_lock(&mymutex);
x = x-5;
cout << "Thread1: x = " << x << endl;
pthread_mutex_unlock(&mymutex);
}
}
void *second(void *){ // function for thread2
for(; i<=5; i++){
pthread_mutex_lock(&mymutex);
x = x/5;
cout << "Thread2: x = " << x << endl;
pthread_mutex_unlock(&mymutex);
}
}
Note I am brand new to the concept threads and mutex. And I'd prefer to stick to the way I have learned in class which I believe is called "the C way".
Thanks to rclgdr who commented above I was able to answer my own question the following code works as intended:
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
using namespace std;
void *first(void *);
void *second(void *);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; // thread1 mutex
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; // thread2 mutex
int x = 19530; // global var that is being manipulated
int main() {
cout << "x = " << x << endl << endl;
int t1, t2;
pthread_t thread1, thread2;
pthread_mutex_lock(&mutex2);
if((t1 = pthread_create( &thread1, NULL, first, NULL))) {
printf("Thread creation failed: %d\n", t2);
}
if((t2 = pthread_create( &thread2, NULL, second, NULL))) {
printf("Thread creation failed: %d\n", t2);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return(0);
}
void *first(void *){ // function for thread1
for(int i = 1; i <=5; i++){
pthread_mutex_lock(&mutex1);
x = x-5;
cout << "Iteration " << i <<endl;
cout << "Thread1: x = " << x << endl;
pthread_mutex_unlock(&mutex2);
}
}
void *second(void *){ // function for thread2
for(int i = 1; i<=5; i++){
pthread_mutex_lock(&mutex2);
x = x/5;
cout << "Thread2: x = " << x << endl << endl;
pthread_mutex_unlock(&mutex1);
}
}
// windows_procon.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <windows.h>
#include <process.h>
using namespace std;
HANDLE mutex;
HANDLE emptySlots;
HANDLE filledSlots;
#define BUFFER_SIZE 10
void *producer(void *);
void *consumer(void *);
int produceItem(void);
void printBuffer(void);
int buffer[BUFFER_SIZE];
int head = 0;
int tail = 0;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD prodThrdID, consThrdID;
mutex = CreateMutex(NULL,FALSE,NULL);
emptySlots = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);
filledSlots = CreateSemaphore(NULL,0,0,NULL);
srand(time(NULL));
_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void*))producer,
0, 0, (unsigned int *)&prodThrdID);
_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void*))consumer,
0, 0, (unsigned int *)&consThrdID);
return 0;
}
void *producer(void *n)
{
int item;
for(int i = 0; i <BUFFER_SIZE+5; i++)
{
WaitForSingleObject(emptySlots,INFINITE);
WaitForSingleObject(mutex,INFINITE);
item = produceItem();
//printf("Producing");
cout << "Producing: " << item << endl;
//logfile << "Producing: "<< item << endl;
//fprintf(logfile, "Producing: %d \n", item);
buffer[head] = item;
head = (head + 1) % BUFFER_SIZE;
printBuffer();
ReleaseMutex(mutex);
ReleaseSemaphore(filledSlots,1, NULL);
}
return n;
}
void *consumer(void *n)
{
for(int i = 0; i <BUFFER_SIZE+5; i++)
{
WaitForSingleObject(filledSlots,INFINITE);
//Sleep(500);
WaitForSingleObject(mutex,INFINITE);
cout << "Consuming: " << buffer[tail] << endl;
buffer[tail] = 0;
tail = (tail + 1) % BUFFER_SIZE;
printBuffer();
ReleaseMutex(mutex);
ReleaseSemaphore(emptySlots,1, NULL);
}
return n;
}
int produceItem(void)
{
int x = (rand()%11 + 1);
return x;
}
void printBuffer(void)
{
for(int i = 0; i <BUFFER_SIZE; i++)
{
printf("%d ", buffer[i]);
}
printf("END \n");
}
My program here is supposed to be an algorithm for the producer-consumer problem. I think I have the algorithm correct my only problem is that I'm having trouble getting the threads to run properly. Can someone tell me what the issue is?
You need to wait for the threads you create with _beginthreadex to do their work, as it stands you program will exit immediately after creating them. I haven't looked any further at you logic.
Here is an example.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
WaitForSingleObject( hThread, INFINITE );
I need to create two threads that strictly alternates. Here is sample code what I use:
#include <Windows.h>
#include <iostream>
using std::cout;
using std::endl;
HANDLE g_hMutex1;
HANDLE g_hMutex2;
DWORD WINAPI ThreadFunc1(LPVOID lpParam);
DWORD WINAPI ThreadFunc2(LPVOID lpParam);
int main(void)
{
int nCalcNumber = 10;
DWORD dwThreadId;
HANDLE pThreadHandles[2];
g_hMutex1 = CreateMutex(NULL, FALSE, NULL);
g_hMutex1 = CreateMutex(NULL, FALSE, NULL);
pThreadHandles[0] = CreateThread(
NULL,
0,
ThreadFunc1,
static_cast<void*>(&nCalcNumber),
0,
&dwThreadId);
pThreadHandles[1] = CreateThread(
NULL,
0,
ThreadFunc2,
static_cast<void*>(&nCalcNumber),
0,
&dwThreadId);
WaitForMultipleObjects(2, pThreadHandles, TRUE, INFINITE);
CloseHandle(pThreadHandles[0]);
CloseHandle(pThreadHandles[1]);
CloseHandle(g_hMutex1);
CloseHandle(g_hMutex2);
return 0;
}
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
cout << "Func 1" << endl;
ReleaseMutex(g_hMutex1);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
cout << "Func 2" << endl;
ReleaseMutex(g_hMutex1);
}
return 0;
}
And a result, which I expect to receive:
Func 1
Func 2
Func 1
Func 2
Func 1
Func 2
...and so one
What should be added to get the desired result. Can I use for that the second mutex?
As noted in other answers, a semaphore is a much better choice than a mutex. But as a purely academic exercise (homework assignment?), you can do this with a mutex, too. (Emphasis: This is a purely academic exercise. A real program shouldn't use this technique.)
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
WaitForSingleObject(g_hMutex2, INFINITE);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
ReleaseMutex(g_hMutex2);
cout << "Func 1" << endl;
ReleaseMutex(g_hMutex1);
WaitForSingleObject(g_hMutex2, INFINITE);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
WaitForSingleObject(g_hMutex2, INFINITE);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
ReleaseMutex(g_hMutex2);
cout << "Func 2" << endl;
ReleaseMutex(g_hMutex1);
WaitForSingleObject(g_hMutex2, INFINITE);
}
return 0;
}
Mutex 1 is the "I have it" mutex, and Mutex 2 is the "I want it next" mutex.
If you can use semaphore: You can use semaphore instead of mutex, it's easy to use same as mutex.
This code works fine:
#include <windows.h>
#include <iostream>
using std::cout;
using std::endl;
PHANDLE sem1;
PHANDLE sem2;
DWORD WINAPI ThreadFunc1(LPVOID lpParam);
DWORD WINAPI ThreadFunc2(LPVOID lpParam);
int main(void)
{
int nCalcNumber = 10;
DWORD dwThreadId;
HANDLE pThreadHandles[2];
sem1 = (PHANDLE) CreateSemaphore(NULL, 1, 1, NULL);
sem2 = (PHANDLE) CreateSemaphore(NULL, 0, 1, NULL);
pThreadHandles[0] = CreateThread(
NULL,
0,
ThreadFunc1,
static_cast<void*> (&nCalcNumber),
0,
&dwThreadId);
pThreadHandles[1] = CreateThread(
NULL,
0,
ThreadFunc2,
static_cast<void*> (&nCalcNumber),
0,
&dwThreadId);
WaitForMultipleObjects(2, pThreadHandles, TRUE, INFINITE);
CloseHandle(pThreadHandles[0]);
CloseHandle(pThreadHandles[1]);
CloseHandle(sem1);
CloseHandle(sem2);
return 0;
}
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*> (lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(sem1, INFINITE);
cout << "Func 1" << endl;
ReleaseSemaphore(sem2, 1 ,NULL);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*> (lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(sem2, INFINITE);
cout << "Func 2" << endl;
ReleaseSemaphore(sem1, 1 ,NULL);
}
return 0;
}
You're assuming that OS actually supports this. Windows doesn't. It has no guarantee about the scheduling, other then no starvation.
So what you need to do is to set a flag variable, so that each thread will change it to allow the other thread to run. For example, if it's true - run, if it's false - release the mutex and sleep for awhile, and the other thread - exactly the opposite. Sleep is important here to avoid starvation and deadlock. I think it can be Sleep(0) (check if it means "yield" in Windows, I'm not sure).
Of course, the checks should be done when the mutex is taken, and at the end of the run each thread will change the variable to the opposite - to allow the other thread to run and block itself until the other thread does run and changes it back.
It can be easily changed to more than 2 threads by making the variable a counter modulo the number of threads, and each thread increasing the value at the end of the run, and checking the value modulo to be the thread's number in order of the execution at the beginning.
edit
volatile bool flag = false;
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; /*no-op*/;)
{
WaitForSingleObject(g_hMutex1, INFINITE);
if (flag) {Sleep(0); continue;}
cout << "Func 1" << endl;
flag = true;
i++;
ReleaseMutex(g_hMutex1);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; /*no-op*/;)
{
WaitForSingleObject(g_hMutex1, INFINITE);
if (!flag) {Sleep(0); continue;}
cout << "Func 2" << endl;
flag = false;
i++;
ReleaseMutex(g_hMutex1);
}
return 0;
}