1 / 1 / 2
Регистрация: 02.06.2009
Сообщений: 83
1

Не могу разобраться с работой потоков

07.09.2013, 17:49. Показов 713. Ответов 14
Метки нет (Все метки)

Сейчас изучаю работу потокв в C#
Для меня основная польза от потоков - что можно работать быстрее,допустим чекер работает в 5 потоков в 5 раз быстрее и т.д
Но я не мону разобраться с кое с чем.Допустим напишем простую программу,которая выводит в цикле числа до 500
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
 class Program
    {
        static object threadLockers = new object();
        static void Main()
        {
            Thread t1 = new Thread(Func); //1 шаг - обьявляем поток
            t1.Start(); //2 шаг - запускам поток
            Thread t2 = new Thread(Func);
            t2.Start();
 
        }
 
        static void Func()
        {
            for (int i = 1; i < 501; i++)
            {
                lock(threadLockers)
                {
                    Console.WriteLine(i);
                    Thread.Sleep(100);
                }
                
            }
            Console.ReadLine();
        }
    }
Тогда программа будем выводить
C++
1
2
3
4
5
6
7
1
1
2
2
3
3
и т.д
Я вроде как заблокировал через lock доступ,но один поток как бы не видит другой и работа не распределяеться
тоесть надо чтобы первый поток выводил 1,а второй уже 2 и т.д я думаю мысль понятна,но не могу понять как это сделать
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.09.2013, 17:49
Ответы с готовыми решениями:

Не могу разобраться с работой программы
Вот код, не могу понять что означает cin&gt;&gt;b,#include &lt;bits/stdc++.h&gt; и sort(b, b + 3); #include...

не могу разобраться с работой роутера
Добрый день. Есть роутер D-Link dir 300,беспроводная дом.сеть : 2 ноутбука,планшетник на...

Не могу разобраться с управлением контрола из левых потоков C# WindowsForm
К примеру мне надо написать Picturebox.Top++; в другом потоке... Напишите пожалуйста что написать...

Задали работу, не могу разобраться. Используется делфи 10, не могу разобраться, как это сделать
В одномерном массиве, состоящем из n вещественных элементов, вычислить: минимальный элемент массива...

14
Master of Orion
Эксперт .NET
6091 / 4947 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
07.09.2013, 18:33 2
Tepper, что происходит в цикле?
  1. заблокировали переменную
  2. пчатаем i
  3. отпускаем захваченную переменную
  4. i++
а вы хотите
  1. заблокировали переменную
  2. пчатаем i
  3. пчатаем i
  4. i++
  5. if (i > 500) break;
  6. отпускаем захваченную переменную
Короче, если вы вынесете lock за пределы цикла, то синхронизирован будет цикл, если оставите в цикле - синхронизация будет только на операцию WriteLine, поэтому они строго последовательно и выводят, то есть варианта 12312 не может быть.
0
1 / 1 / 2
Регистрация: 02.06.2009
Сообщений: 83
07.09.2013, 18:47  [ТС] 3
Ну тогда получаеться что у меня работает как 1 поток!
а мне надо чтобы выводило
1- поток1
2- поток2
3- поток1
0
2809 / 2000 / 588
Регистрация: 02.08.2011
Сообщений: 5,557
07.09.2013, 18:52 4
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
 internal class LockingIterator
    {
        public int counter = 0;    
    }
 
 
    class Program
    {  
        static int[] mas = Enumerable.Range(1,100).ToArray();
        static LockingIterator iter = new LockingIterator();
 
        static void Main(String[] arg)
        {
            Thread thr = new Thread(ShowValue);
            thr.Start();
            Thread thr2 = new Thread(ShowValue);
            thr2.Start();
           Console.ReadKey(true);        
        }
 
      private static void ShowValue()
        {
            for (;; iter.counter++)
            {
                lock (iter)
                    if (iter.counter < mas.Length)
                        Console.WriteLine(mas[iter.counter] + "  ThreadId:" + Thread.CurrentThread.ManagedThreadId);
                    else break;
            }
         }
0
Темная сторона .Net
590 / 487 / 39
Регистрация: 21.07.2012
Сообщений: 1,668
07.09.2013, 18:56 5
Tepper, вы понимаете что если винда не запустит на 2-х или более ядрах запустит ваше приложение на 1-ом ядре, то этот ад станет еще жарче?
0
2809 / 2000 / 588
Регистрация: 02.08.2011
Сообщений: 5,557
07.09.2013, 18:56 6
но строго поочередно все равно не получается контролировать. Будет интересно, если покажете решение. )
0
1 / 1 / 2
Регистрация: 02.06.2009
Сообщений: 83
07.09.2013, 19:00  [ТС] 7
Спасибо я как раз уже сделал с добавление статической переменной счетчиком и условием,так работает
да строго поочередно не получаеться и не обязательно,мне важно что-бы при 2ух потоках работало быстрее просто в 2 раза.Но это просто как пример
Если у меня будет парсер какойнибудь,при большем кол-во потоков с такой реализацией(переменной-счетчиком) все будет работать быстрее?
0
2809 / 2000 / 588
Регистрация: 02.08.2011
Сообщений: 5,557
07.09.2013, 19:07 8
Будет быстрее, но не думаю, что строго в два раза. Можно проверить.
0
136 / 138 / 18
Регистрация: 26.07.2010
Сообщений: 911
07.09.2013, 19:18 9
Кликните здесь для просмотра всего текста

Цитата Сообщение от Tepper Посмотреть сообщение
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
 class Program
    {
        static object threadLockers = new object();
        static void Main()
        {
            Thread t1 = new Thread(Func); //1 шаг - обьявляем поток
            t1.Start(); //2 шаг - запускам поток
            Thread t2 = new Thread(Func);
            t2.Start();
 
        }
 
        static void Func()
        {
            for (int i = 1; i < 501; i++)
            {
                lock(threadLockers)
                {
                    Console.WriteLine(i);
                    Thread.Sleep(100);
                }
                
            }
            Console.ReadLine();
        }
    }

Ужасный пример для работы с потоками, это раз.
Цитата Сообщение от Tepper Посмотреть сообщение
Я вроде как заблокировал через lock доступ,но один поток как бы не видит другой и работа не распределяеться
то есть надо чтобы первый поток выводил 1,а второй уже 2 и т.д я думаю мысль понятна,но не могу понять как это сделать
Вы заблокировали только вывод переменной в консоль, метод запущенный в двух потоках выполняет одно и то-же действие, с разными переменными. Блокировка тут не выполняет своей роли.
Вот так сработает, но вообще, это очень плохой пример.
Кликните здесь для просмотра всего текста

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
    class Program
    {
        static object threadLockers = new object();
        static void Main()
        {
            MyClass val = new MyClass();
            val.Value = 1;
            Thread t1 = new Thread(Func); //1 шаг - обьявляем поток
            t1.Start(val); //2 шаг - запускам поток
            Thread t2 = new Thread(Func);
            t2.Start(val);
 
        }
 
        static void Func(object val)
        {
            MyClass value = (MyClass)val;
            while (value.Value < 501)
            {
                lock (threadLockers)
                {
                    Console.WriteLine(value.Value);
                    value.Value++;
                    Thread.Sleep(100);
                }
            }
            Console.ReadLine();
        }
    }
 
    class MyClass
    {
        public int Value { get; set; } 
    }


Добавлено через 1 минуту
Цитата Сообщение от IamRain Посмотреть сообщение
Будет быстрее, но не думаю, что строго в два раза. Можно проверить.
Будет не быстрее, а медленнее.
1
2809 / 2000 / 588
Регистрация: 02.08.2011
Сообщений: 5,557
07.09.2013, 19:25 10
Цитата Сообщение от n1l Посмотреть сообщение
Будет не быстрее, а медленнее.
Ну да, проверил,виноват, действительно медленнее.
39 мс одним потоком и 43 двумя. Так понимаю, из-за постоянных блокировок.
Ну это на такой простой задаче, а если бы какие то длительные вычисления, думаю, оправдало бы.
0
Master of Orion
Эксперт .NET
6091 / 4947 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
07.09.2013, 19:39 11
Цитата Сообщение от IamRain Посмотреть сообщение
но строго поочередно все равно не получается контролировать. Будет интересно, если покажете решение. )
Насколько я помню, fibers может это делать ровно поочередно. Благо в винде они есть. Так что не правы.

Добавлено через 1 минуту
Кстати я с ними уже писал, достаточно перевести
Работа с потоками. ч2. Fibers
0
2809 / 2000 / 588
Регистрация: 02.08.2011
Сообщений: 5,557
07.09.2013, 19:44 12
Цитата Сообщение от Psilon Посмотреть сообщение
Так что не правы.
Имел ввиду, что не получается у меня. )
0
447 / 305 / 47
Регистрация: 23.01.2013
Сообщений: 661
07.09.2013, 21:59 13
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
    class Program
    {
        static int m = 0;
        static object LockObj = new object();
 
        static void Main(string[] args)
        {
            Thread th1 = new Thread(ThreadMethod);
            Thread th2 = new Thread(ThreadMethod);
            th1.Name = "Thread 1";
            th2.Name = "Thread 2";
            th1.Start();
            th2.Start();
 
            Console.ReadLine();
        }
 
        static void ThreadMethod()
        {
            for (int i = 0; i < 5; i++)
            {
                lock (LockObj)
                {
                    Monitor.PulseAll(LockObj);
                    Monitor.Wait(LockObj);
 
                    m++;
                    Console.WriteLine("{0} : {1}", Thread.CurrentThread.Name, m);
                }
            }
        }
    }
1
2809 / 2000 / 588
Регистрация: 02.08.2011
Сообщений: 5,557
08.09.2013, 09:07 14
Цитата Сообщение от Anklav Посмотреть сообщение
Monitor.PulseAll(LockObj);
* * * * * * * * * * Monitor.Wait(LockObj);
Только надо после вывода на консоль выполнять, так как один из потоков, который последнее число (10) выводит, сам себя заблокирует и 10 не отображается на консоли поэтому.
0
Master of Orion
Эксперт .NET
6091 / 4947 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
08.09.2013, 13:48 15
Anklav, я написал что-то вроде шедулера, но он почему-то в дебаге если проходить по F10 работает, а если просто запустить - нифига. Как заставить его работать нормально идей нет, на stackoverflow за сутки ни 1 ответа
Так что можете сами прикинуть. Смысл в том, что шедулер не знает ничего про action, которые от него хотят выполнить, он просто должен выделить каждой задаче определенный интервал времени на выполнение:
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
using System;
using System.Collections.Generic;
using System.Threading;
 
namespace ConsoleApplication143
{
    internal class Program
    {
        private static void Main()
        {
            const int n = 5;
            ThreadStart start = () =>
                                {
                                    for (int i = 0; i < n; i++)
                                        Console.WriteLine("{0} {1}", i, Thread.CurrentThread.ManagedThreadId);
 
                                };
            var rrs = new RobinRoundSheduler(2, start) {TimeForTask = new TimeSpan(1)};
            rrs.Start();
            Console.ReadKey();
        }
    }
 
 
    internal class RobinRoundSheduler
    {
        private readonly LinkedList<Thread> _threads;
        public TimeSpan TimeForTask { get; set; }
 
        public RobinRoundSheduler(int taskCount, ThreadStart start)
        {
            TimeForTask = TimeSpan.FromSeconds(1);
            _threads = new LinkedList<Thread>();
            for (int i = 0; i < taskCount; i++)
            {
                _threads.AddLast(new Thread(start));
            }
        }
 
        public void Start()
        {
            while (_threads.Count > 0)
            {
                var list = new List<Thread>();
                foreach (var thread in _threads)
                {
                    lock (thread)
                    {
                        if (thread.ThreadState == ThreadState.Unstarted)
                            thread.Start();
                        else
                            thread.Resume();
                    }
                    thread.Join(TimeForTask);
                    lock (thread)
                    {
                        if (thread.ThreadState == ThreadState.Stopped || thread.ThreadState == ThreadState.Aborted)
                            list.Add(thread);
                        else
                        {
                            thread.Suspend();
                        }
                    }
                }
                list.ForEach(thread => _threads.Remove(thread));
            }
        }
    }
}
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.09.2013, 13:48
Помогаю со студенческими работами здесь

Прошу разобраться с курсовой работой
Был дан пример с кодом ( говорили что правильный) но у меня он не срабатывает. Помогите разобраться...

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

Разобраться с работой события СellClick в DataGridView
доброе время суток, помогите разобраться с работой события СellClick в DataGridView На форме...

Помогите разобраться с работой FOR на данных примерах
1) Создать две директории. Наполнить одну из них несколькими файлами. При помощи ключевого слова...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru