Работа с потоками, используя защелку

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Gruvna
Сообщения: 2
Зарегистрирован: 22 дек 2015, 10:14

Нужна помощь, нужно разработать программу редактирование документа с 2 потоками используя защелку. Пока 1 поток работает, во втором должна быть ошибка. В 2х разных консолях.
Часть кода, не понятно почему не захватывает файл

Код: Выделить всё

void MyClass::SetName()
{
	CSingleLock myLock(&Mymutex);
	myLock.Lock();
	ofstream F;
	F.open("text.txt", ios: :o ut);
	char jsdfhu[256];
	cout << "vvedite choto\n";
	cin >> jsdfhu;
	F << jsdfhu;
	if (!F.is_open())
	{
		char jsdfhu[256];
		cout << "vvedite choto\n";
		cin >> jsdfhu;
		F << jsdfhu;
	}
	else 
	{
		 cout << " oshibko.\n";
	}
	system("pause");
	F.close();
}
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Недостаточно кода, чтобы понять, в чём проблема. Например, не видно, как создаётся Mymutex. Если он создан неправильно, то, например, возможна ситуация, что каждый поток создаёт собственный мьютекс, так что второй поток успешно лочит свой мьютекс, и ему ничего не мешает зайти в критическую секцию и упасть при попытке открыть файл, который уже открыт на запись первым потоком.

По заданию тоже есть непонимание. Сначала там говориться о двух потоках. Затем есть упоминание о двух разных консолях, что намекает уже о том, что это не два потока, а два процесса. Можно ли прояснить этот пункт?
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Gruvna
Сообщения: 2
Зарегистрирован: 22 дек 2015, 10:14

Код: Выделить всё

public:
	MyClass();         
	void SetName();
	~MyClass();
	CMutex Mymutex;
у меня должно быть открыто 2 приложения первое получило доступ к файлу и ждет от меня ввода с клавиатуры чего то там... второе при запуске выдает ошибку из-за того что файл уже захвачен,но на данный момент выходит так что файл не захвачивается и в 2х приложениях ожидание ввода значения
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Во-первых что-то не понимаю нафига тут вообще нужна защелка (мьютекс, если выражаться на нормальном программистском языке), если можно просто открыть файл в эксклюзивном режиме? Мьютекс нужен не для того чтобы заблокировать ресурс, то есть в нашем случае файл, для конкурентного процесса, а чтобы синхронизировать работу с конкурентным процессом. Например, если конкурентные процессы будут писать в файл или читать из файла только предварительно захватив мьютекс, то ни один из процессов не сможет увидеть файл в промежуточном (поломанном) состоянии когда кто-то другой начал его изменять и еще не закончил. Мьютекс, кстати, должен быть глобальным и именованным чтобы была только одна копия в рамках всей операционной системы. Иначе у каждого процесса будет свой мьютекс и захват одного мьютекса не будет мешать параллельному захвату другого мьютекса и никакой синхронизации происходить не будет.

Лет 15 уже не тыкал палочкой в MFC, но судя по тому что я вижу у класса CMutex есть параметр в конструкторе - имя мьютекса. если его не указать, а ты его не указываешь, то мьютекс будет локальным. А тебе нужен глобальный.

Код: Выделить всё

CMutex Mymutex(FALSE, "my-cool-mutex-42"); //Имя должно быть уникальным чтобы избежать коллизий. Лучше взять GUID: https://www.guidgenerator.com/online-guid-generator.aspx
2B OR NOT(2B) = FF
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Ага, собственно именно то, что я и ожидал. При таком объявлении у каждого объекта MyClass будет свой экземпляр мьютекса, и эти экземпляры никак не будет мешать друг другу заходить в критическую секцию кода. Такой подход нужен только в том случае, если методы класса будут вызываться в разных потоках для одного и того же объекта, иными словами, если требуется синхронизировать доступ к this. У нас же по заданию требуется другое - синхронизировать доступ к файлу. В следствие того, что файл один на всех, то и мьютекс, которым будем синхронизировать доступ, тоже должен быть один на всех. То есть, если синхронизировать нужно два потока, то мьютекс нужно делать статическим, а если нужно синхронизировать вообще два экземпляра приложения, то следует делать глобальный именованный мьютекс, как указал Absurd.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Gruvna писал(а):

Код: Выделить всё

public:
	MyClass();         
	void SetName();
	~MyClass();
	CMutex Mymutex;
у меня должно быть открыто 2 приложения первое получило доступ к файлу и ждет от меня ввода с клавиатуры чего то там... второе при запуске выдает ошибку из-за того что файл уже захвачен,но на данный момент выходит так что файл не захвачивается и в 2х приложениях ожидание ввода значения
Креэйтфайл без шары.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

Возможно функция CreateFile() с определёнными параметрами (или без таковых) позволит как-то улучшить ситуацию, но это всё равно будет не лучшим решением.
Сам факт того, что несколько приложений одновременно должны набрасываться на один файл, говорит о непродуманности системы.
Решается такая задача с помощью клиент-серверной архитектуры.
Т.е. один какой-то один процесс (сервер) имеет монопольный доступ к определённым файлам,
а другие приложения (клиенты) обращаются к нужному файлу опосредованно через этот сервер.
Самое простое решение - использовать готовый FTP-сервер, который можно установить как на локальной машине, так и на удалённой.
Если захочется самому написать некий свой сервер, то для этого Microsoft Visual C++ предлагает как минимум два варианта решения:
- локальный СОМ-сервер (LocalServer)
- Служба Windows (Windows service)
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Да здесь ни о какой "правильной" архитектуре и не шла речь никогда. Насколько я понял, это просто упражнение на использование мьютексов. Так что на притянутость за уши самой постановки не стоит обращать внимания :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Возможно функция CreateFile() с определёнными параметрами (или без таковых) позволит как-то улучшить ситуацию, но это всё равно будет не лучшим решением.
Сам факт того, что несколько приложений одновременно должны набрасываться на один файл, говорит о непродуманности системы.
Решается такая задача с помощью клиент-серверной архитектуры.
Помнится давным давно, когда я еще был студентом последнего курса, на SQL.ru водился сочнейший тролль "Люблю ФС" который с невозмутимым видом доказывал тамошним аскакалам что свалка dBASE/Paradox/FoxPro/* файлов на сетвой шаре надежно работает с любым количеством пользоватлей и что это работает быстрее любого SQL. Там все были готовы растерзать мерзкого святотатца, но тот похоже был какой-то редкий спец и знал все тончайшие нюансы про совместный доступ к файлам на нетварной шаре и все аргументы отскакивали от него как горох от бетонной стены.
2B OR NOT(2B) = FF
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

Возможно этот специалист по SQL был действительно прав.
Ведь служба доступа к файлам и принтерам - это один из сетевых сервисов Windows.
Таким образом мы неявно переводим систему хранения данных на клиент-серверную архитектуру.
Взаимодействие между файловым сервером и клиентом происходит по SMB-протоколу.
С таким же успехом это можно делать и на локальной машине,
т.е. обращаться к собственным файлам не напрямую, а через службу сетевого доступа по протоколу SMB.
Ответить