С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/23: Рейтинг темы: голосов - 23, средняя оценка - 4.87
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21

Синхронизация потоков

09.09.2009, 16:50. Показов 4593. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Не пойму своей ошибки в этих двух примерах кода, пожалуйста подскажите.

Синхронизация с помощью мьютексов.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
 
namespace TestThread
{
    class Program
    {
        public delegate int MainFuncDel(int data, int ms);
        static void ThreadMainWithParameters(object dat)
        {
            CountTasks data = (CountTasks)dat;
            Mutex m = Mutex.OpenExisting("TestMutex");
            for (int i = 0; i < 50000; i++)
            {
                if (m.WaitOne(-1,false))
                {
                    data.Inc();
                }
                else
                {
                    Console.WriteLine("Произошла какая-то проблема");
                }
                m.ReleaseMutex();                
            }
        }
        public class CountTasks
        {
            private int count;
            private object syncRoot = new object();
            public int Count 
            {
                get { return count; }
                set { count = value;}
            }
            public void Inc()
            {
                    ++count;
            }
            public void Zero()
            {
                count = 0;
            }
        }
 
        public struct Data
        {
            public string Message;
        }
        static void Main(string[] args)
        {
            bool cn;
            Mutex mutex = new Mutex(false, "TestMutex",out cn);
            CountTasks count = new CountTasks();
            Thread[] threads = new Thread[20];
            for (int j = 0; j < 20; j++)
            {
                for (int i = 0; i < 20; ++i)
                {
                    threads[i] = new Thread(ThreadMainWithParameters);
                    threads[i].Start(count);
                }
                Console.WriteLine("Результат цикла {1} = {0}", count.Count,j);
                count.Zero();
            }
            
            Console.ReadKey();
        }
        
    }
}
А в этом участке с помощью оператора long, ну как я понимаю это аналог критических секций.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
 
namespace TestThread
{
    class Program
    {
        public delegate int MainFuncDel(int data, int ms);
        static void ThreadMainWithParameters(object dat)
        {
            CountTasks data = (CountTasks)dat;
            
            for (int i = 0; i < 50000; i++)
            {
                lock (data)
                {
                    data.Count += 1;
                }
                
            }
        }
        public class CountTasks
        {
            private int count;
            private object syncRoot = new object();
            public int Count 
            {
                get { return count; }
                set { count = value;}
            }
            public void Inc()
            {
                lock (this)
                {
                    Interlocked.Increment(ref count);
                }
            }
            public void Zero()
            {
                count = 0;
            }
        }
 
        public struct Data
        {
            public string Message;
        }
        static void Main(string[] args)
        {
            CountTasks count = new CountTasks();
            Thread[] threads = new Thread[20];
            for (int j = 0; j < 20; j++)
            {
                for (int i = 0; i < 20; ++i)
                {
                    threads[i] = new Thread(ThreadMainWithParameters);
                    threads[i].Start(count);
                }
                Console.WriteLine("Результат цикла {1} = {0}", count.Count,j);
                count.Zero();
            }
            
            Console.ReadKey();
        }
        
    }
}
Результат в обоих случаях должен быть 1000000. Но что-то не так сделано наверное. Если кто знает, подскажите, что не так?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.09.2009, 16:50
Ответы с готовыми решениями:

Синхронизация потоков
В общем идея была в том, что создаётся список потоков List&lt;Thread&gt; threads;. Все эти потоки стартуют выполнять одну и ту же функцию. ...

Синхронизация потоков
Подскажите как сделать так, чтоб потоки выполнялись по порядку вот такой простой код using System; using System.Diagnostics; ...

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

16
4 / 4 / 0
Регистрация: 05.09.2009
Сообщений: 11
09.09.2009, 18:06
Какая у тебя задача стоит? Какой результат тебе нужен?
Исходя из того что ты привел, то ты пинаешь поочередно 20 потоков, которые начинают наращивать count. После запуска каждого потока ты выводишь текущее значение count, которое изменяется всеми запущенными потоками. Т.е. count ты получаешь такой, каким он успел стать со времени обнуления count до вывода следующего значения count. А потоки ты здесь по всей вероятности не синхронизируешь, а защищаешь данные от совместного использования. В данном случае данные - это экземпляр CountTasks.
0
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
09.09.2009, 18:18  [ТС]
Верно, разделение ресурсов. Хотя по сути похоже. Задача такова - нас есть 20 потоков с 50000 итераций в каждом. На выходе должен получиться 1000000. А его не получается. Надо чтобы получался. Ну это чтоб точно знать что разделяем ресурс правильно
0
Администратор
 Аватар для mik-a-el
87827 / 53148 / 249
Регистрация: 10.04.2006
Сообщений: 13,761
09.09.2009, 18:20
discens, а зачем вы для блокировки используете тот же самый объект? Лучше используйте отдельный объект, например строку, содержащую Guid.
0
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
09.09.2009, 18:23  [ТС]
да ну что бы доступа к нему не было. А эт важно?
0
Администратор
 Аватар для mik-a-el
87827 / 53148 / 249
Регистрация: 10.04.2006
Сообщений: 13,761
09.09.2009, 18:25
Лучший ответ Сообщение было отмечено mik-a-el как решение

Решение

Да, важно. Потому что вот так работает:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
 
namespace TestThread
{
    class Program
    {
        public delegate int MainFuncDel(int data, int ms);
        static void ThreadMainWithParameters(object dat)
        {
            CountTasks data = (CountTasks)dat;
 
            for (int i = 0; i < 50000; i++)
            {
                lock ("sdfbsdbsdfbsdbsgsfb")
                {
                    data.Count += 1;
                }
 
            }
        }
        public class CountTasks
        {
            private int count;
            private object syncRoot = new object();
            public int Count
            {
                get
                {
                    return count;
                }
                set
                {
                    count = value;
                }
            }
            public void Inc()
            {
                lock ("asfdvsdfvsdvsdvsdsss")
                {
                    Interlocked.Increment(ref count);
                }
            }
            public void Zero()
            {
                count = 0;
            }
        }
 
        public struct Data
        {
            public string Message;
        }
        static void Main(string[] args)
        {
            CountTasks count = new CountTasks();
            Thread[] threads = new Thread[20];
            for (int j = 0; j < 20; j++)
            {
                for (int i = 0; i < 20; ++i)
                {
                    threads[i] = new Thread(ThreadMainWithParameters);
                    threads[i].Start(count);
                }
                Console.WriteLine("Результат цикла {1} = {0}", count.Count, j);
                count.Zero();
            }
 
            Console.ReadKey();
        }
 
    }
}
0
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
09.09.2009, 18:26  [ТС]
а вообще я для увеличения значения, использую эту функцию
C#
1
2
3
4
5
6
7
public void Inc()
            {
                lock (this)
                {
                    Interlocked.Increment(ref count);
                }
            }
тут аж с двойной блокировкой...
то я просто в коде забыл вставить правильно. Но всё равно, правильно не разделяет
0
Администратор
 Аватар для mik-a-el
87827 / 53148 / 249
Регистрация: 10.04.2006
Сообщений: 13,761
09.09.2009, 18:28
Подождите, что-то вы там намудрили, нужно глубже копать...
0
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
09.09.2009, 18:29  [ТС]
а вы уверены что у вас работает? потому что у меня нет. Если не тяжело, скажите зачем строку ставить. Я так понимаю надо ставить объект который блокируется?
0
4 / 4 / 0
Регистрация: 05.09.2009
Сообщений: 11
09.09.2009, 19:03
Цитата Сообщение от mik-a-el Посмотреть сообщение
Да, важно. Потому что вот так работает:
Так не работает. С чего вы взяли что после каждого цикла for (int i = 0; i < 20; ++i)... вы получите 1000000? Ну может на вашей машине вы такое и получите, на другой это работать не будет.
Смысла в lock ("asfdvsdfvsdvsdvsdsss") {...} нет поскольку каждый раз создается новый string, который и является разделяемым ресурсом. Чтоб синхронизироваться нужно блокировать общий ресурс.

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

Добавлено через 15 минут
Цитата Сообщение от discens Посмотреть сообщение
Верно, разделение ресурсов. Хотя по сути похоже. Задача такова - нас есть 20 потоков с 50000 итераций в каждом. На выходе должен получиться 1000000. А его не получается. Надо чтобы получался. Ну это чтоб точно знать что разделяем ресурс правильно
Не получится. А разделяете ресурсы вы по-моему правильно. По крайней мере в случае с lock на первый взгляд все в порядке.

У mik-a-el все "как бы" заработало, потому что собсно никакие ресурсы не разделялись и потоки работали без блокировок, т.е. поживее немного. Поэтому они успевали насчитать 1000000, но не всегда.
1
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
09.09.2009, 19:09  [ТС]
ну, было пару раз что и болье 2000000 насчитало, было что и ровно 1000000. В том то и дело что правильно, а практике не фурычит))).
Ну а что подскажете насчёт мьютексов? там я так понимаю происходит взаимоблокировка процессов, потому что и за 10000 значение не выходит. Хотя с виду вроде бы всё то... Казалось бы такая простая задачка, а тут вот тебе.
0
4 / 4 / 0
Регистрация: 05.09.2009
Сообщений: 11
09.09.2009, 19:29
Да правильно все у тебя. Потоки работают параллельно. Ты пнул 20 раз ThreadMainWithParameters и они себе и будут работать, а когда ты выводишь Console.WriteLine("Результат цикла {1} = {0}", count.Count,j); то не факт что все они отработали. Может быть и отработали, а скорее всего парочка из них недоработала, поэтому когда ты запускаешь новые 20 потоков то над одним countом не факт что будут работать именно 20 потоков, а вдруг с прошлой 20-ки кто-то не закончил. Поэтому либо запускать циклы последовательно, но тогда смысла в задаче никакой, либо создавать 20 разделяемых ресурсов для каждого потока в отдельности, потом каждый поток блокирует свой ресурс, а ожидать освобождения в main нужно. А если задача такая, что нужно в параллельном потоке чего-нибудь посчитать и вернуть данные в текущий поток, то смотри в сторону ManualResetEvent или мьютексов.

Вот тебе синхронизирующий потоки класс. В одном потоке ты создаешь экземпляр запускаешь поток с вычислениями, а дальше можешь делать че хочешь, только в конце метода вызываешь Wait(), чтоб дождаться результатов работы параллельного патока. А в потоке с вычислениями, после проведения всех операций делаешь UnlockMutex(). Ну а результат можно запихнуть в Data:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    public class SynсClass
    {
        object _Data = null;
 
        public object Data
        {
            get { return _Data; }
            set { _Data = value; }
        }
        public ManualResetEvent Mut = new ManualResetEvent(false);
        /// <summary>
        /// Ожидание... тайм аут 10 секунд
        /// </summary>
        /// <returns></returns>
        public bool Wait()
        {
            return Wait(10000);
        }
 
        public bool Wait(int TimeOut)
        {
            bool RetVal = Mut.WaitOne(TimeOut, false);
            return RetVal;
        }
        public void UnlockMutex()
        {
            Mut.Set();
        }
 
    }
Ежели Wait вернул false, то случился таймаут ожидания окончания вычислений.
1
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
09.09.2009, 19:36  [ТС]
Спасибо Андрей, а в том коде где я с мьютексами работал, ты на первый взгляд ошибку нигде не видишь?
0
4 / 4 / 0
Регистрация: 05.09.2009
Сообщений: 11
09.09.2009, 19:51
вроде все нормально.
0
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
09.09.2009, 20:32  [ТС]
Насчёт того что потоки может не успевают, ты может и прав вот что вышло когда писалось на WinApi C++
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <Windows.h>
#include <conio.h>
int CountTasks=0;
CRITICAL_SECTION g_cs;
DWORD WINAPI ThreadInfo(LPVOID)
        {   
            //MessageBox(0,0,0,0);
            for (int i = 0; i < 50000; i++)
            {
                EnterCriticalSection(&g_cs);
                ++CountTasks;
                LeaveCriticalSection(&g_cs);
            }
            return 0;
        }
int main()
{
    DWORD ThreadInfoId[20];
    HANDLE hThreadInfo[20];
    InitializeCriticalSection(&g_cs);
    for (int i=0;i<20;++i)
    {
        hThreadInfo[i]=CreateThread(0,0,ThreadInfo,NULL,0,&ThreadInfoId[i]);    
    }
    WaitForMultipleObjects(20,hThreadInfo,true,-1);
    DeleteCriticalSection(&g_cs);
    printf("end = %d",CountTasks);
    getch();
    return 0;
}
то тут всё ок. Хм, в книжке по С# , было написано что так как я делал, всё должно быть нормально.
0
4 / 4 / 0
Регистрация: 05.09.2009
Сообщений: 11
10.09.2009, 11:35
Там ведь ты вызываешь вот это: WaitForMultipleObjects(20,hThreadInfo,tr ue,-1); в main. Попробуй printf сделать до этого вызова.

Добавлено через 13 минут
Цитата Сообщение от discens Посмотреть сообщение
Хм, в книжке по С# , было написано что так как я делал, всё должно быть нормально.
А что за книжка? Я может тоже просвещусь.

Добавлено через 1 час 20 минут
В общем вот тоже самое что и на С++ только на C#. Если ты закоментишь в этом коде WaitForMultipleObjects(20, Handlers, true, -1);, то получишь примерно туже чушь что и в первом твоем примере.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace TestThread
{
    class Program
    {
        #region Imports
        [DllImport("kernel32.dll")]
        public static extern uint WaitForMultipleObjects(
            uint nCount,
            [In] IntPtr[] handles,
            bool bWaitAll, 
            int dwMilliseconds);
 
        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateThread(IntPtr lpThreadAttributes,
             int dwStackSize,
             [MarshalAs(UnmanagedType.FunctionPtr)] DThread lpStartAddress,
             IntPtr lpParameter,
             int dwCreationFlags,
             out  IntPtr lpThreadId
            );
        #endregion
 
        static int count = 0;
        static object SyncObj = new object();
        public delegate void DThread();
        public static void ThreadMainWithParameters()
        {
            for (int i = 0; i < 50000; i++)
            {
                lock (SyncObj)
                {
                    ++count;
                }
            }
        }
        static unsafe void Main(string[] args)
        {
 
            IntPtr[] threads = new IntPtr[20];
            IntPtr[] Handlers = new IntPtr[20];
            DThread MyD = new DThread(ThreadMainWithParameters);
            for (int j = 0; j < 10; j++)
            {
                for (int i = 0; i < 20; i++)
                {
                    Handlers[i] = CreateThread(IntPtr.Zero, 0, MyD, IntPtr.Zero, 0, out threads[i]);
                }
                WaitForMultipleObjects(20, Handlers, true, -1);
                Console.WriteLine("Результат цикла  = {0}", count);
                count = 0;
            }
            Console.ReadKey();
        }
 
    }
}
1
0 / 0 / 0
Регистрация: 28.01.2009
Сообщений: 21
16.09.2009, 09:17  [ТС]
книжка называется - C# 2005 и платформа .NET 3.0 для профессионалов (Кристиан Нейгел и др.)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.09.2009, 09:17
Помогаю со студенческими работами здесь

Синхронизация потоков
Гуглю уже долго, а ответа все так и не нашел. Ситуация такая. У меня есть метод, который выполняют несколько потоков одновременно: ...

Синхронизация потоков, мьютекс
я имею функцию, которую запускаю в несколько потоков public static void FuckingThread(StreamWriter kok, Regex RegExp) ...

Синхронизация групп потоков
Здравствуйте! Помогите, пожалуйста. У меня есть метод MonitoringThread() в котором запускается 9 потоков. Мне необходимо чтобы каждые из...

Асинхронный сокет синхронизация потоков
Нужно сделать синхронизацию каталогов на сервере и на клиенте используя неблокирующий сокет. Использую асинхронный. На сервере и на...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru