[SOLVED] Проблемы с мультипоточностью.


photo

Recommended Posts

Добрый день!

Странная проблема с инициализацией потоков.

В отладчике, с заходом в инициализацию переменной объектов, потоки запускаются и отрабатывают без проблем.
Если код запустить без прохода отладчиком, выполняется только один объект в основном потоке.

Не понимаю что могло пойти не так.

if (Input::isKeyUp(Input::KEY_B))
	{
		MyThread th3;
		MyThread th4;
		th3.run();
		th4.run();
		th3.setValue(0);
		th4.setValue(9);
		th3.stop();
		th4.stop();
	}
#pragma once
  
#include <UnigineThread.h>

using namespace Unigine;

class MyThread : public Thread
{
public:
	MyThread();
	~MyThread();

	void setValue(int value);
	int getValue() const;

private:
	int a = 0;
	mutable Mutex lock;
	void process() override;
};
#include "MyThread.h"

MyThread::MyThread()
{
}
MyThread::~MyThread()
{
}

void MyThread::setValue(int value)
{
	//ScopedLock atomic(lock);
	a = value;
}
int MyThread::getValue() const
{
	//ScopedLock atomic(lock);
	return a;
}

void MyThread::process()
{	
	for (size_t i = 0; i < 5; i++)
	{		
		a++;
		//lock.lock();
		Log::message("ID = %d\n", getID());
		Log::message("VAL = %d\n", a);
		Log::message("\n......................\n");
		//lock.unlock();
		sleep(2000);
	}	
}

С Уважением, Константин!

thread_test.zip

Edited by Vasara
Link to post

Добрый день.

run не запускает поток незамедлительно, он лишь сообщает ОС, что можно запустить поток. ОС сама запустит поток как только будет возможность. 
для решения этой проблемы можно добавить метод waitRunning

 


class MyThread : public Thread
{
public:
	MyThread();
	~MyThread();

	void setValue(int value);
	int getValue() const;

private:
	int a = 0;
	mutable Mutex lock;
	mutable Mutex lock_running; // additional mutex
	void process() override;
};
#include "MyThread.h"

MyThread::MyThread()
{
lock_running.lock(); // lock this mutex in constructor
}
MyThread::~MyThread()
{
}

void MyThread::setValue(int value)
{
	//ScopedLock atomic(lock);
	a = value;
}
int MyThread::getValue() const
{
	//ScopedLock atomic(lock);
	return a;
}

void waitRunning() const
{
	lock_running.lock(); // wait for lock_running will be unlocked
}


void MyThread::process()
{	
lock_running.unlock() // and unlock when thread is realy started 
	for (size_t i = 0; i < 5; i++)
	{		
		a++;
		//lock.lock();
		Log::message("ID = %d\n", getID());
		Log::message("VAL = %d\n", a);
		Log::message("\n......................\n");
		//lock.unlock();
		sleep(2000);
	}	
}


вы можете вызывать этот метод как самостоятельно 

MyThread th3;
MyThread th4;
th3.run();
th4.run();
th4.waitRunning(); 
th3.waitRunning(); // wait real running
th3.setValue(0);
th4.setValue(9);
th3.stop();
th4.stop();

так и добавить его внутрь метода run

virtual int MyThread::run(size_t size = 0x100000) override
{
	Thread::run(size);
	waitRunning();
}

Это зависит от того, какое поведение вы ожидаете.

иначе stop успевает вызываться до того, как поток вообще был запущен - поэтому у вас разное поведение при остановке отладчиком -  при остановке потоки успевают нормально запустится. 

этот баг(или не баг?) пофишкен в 2.14. мы добавили проверку при остановке потока.

Link to post
2 hours ago, cash-metall said:

run не запускает поток незамедлительно, он лишь сообщает ОС, что можно запустить поток.

Спасибо, картинка сложилась, почему поведение отличалось от стдшного скрипта.

 

Думаю любой результат работы методов, отличный от заявленного в документации, можно относить к багам.

Link to post
  • Vasara changed the title to [SOLVED] Проблемы с мультипоточностью.