当前位置: 移动技术网 > IT编程>开发语言>c# > C#多线程基础

C#多线程基础

2019年09月03日  | 移动技术网IT编程  | 我要评论

最近自己写了个小爬虫,里面用到了多线程技术,忽然发现对此技术竟然有些陌生了,于是乎开始疯狂的去问度娘,在此记录下来,以便自己和各位小伙伴们学习。

一、什么是线程

一个应用程序就相当于一个进程,进程拥有应用程序的所有资源进程包括线程,进程的资源被线程共享,但不拥有线程。我们可以打开电脑中的任务管理器,运行的.exe都是一个进程,里面的分支是线程。

二、多线程

多线程其实就是进程中一段并行运行的代码

1. 创建并启动线程

 1         static void main()
 2         {
 3             //获取线程id
 4             var threadid = thread.currentthread.managedthreadid;
 5             var thread = new thread(test1);
 6             thread.start();
 7 
 8             console.writeline(threadid + "_main()");
 9             console.read();
10         }
11 
12         /// <summary>
13         /// 测试方法
14         /// </summary>
15         private static void test1()
16         {
17             //获取线程id
18             var threadid = thread.currentthread.managedthreadid;
19             console.writeline(threadid + "_test()");
20             for (int i = 0; i < 10; i++)
21             {
22                 console.writeline(threadid + "_" + i);
23             }
24         }

结果:

 

 

 2、暂定线程诺干时间

 1         static void main()
 2         {
 3             //获取线程id
 4             var threadid = thread.currentthread.managedthreadid;
 5             var thread = new thread(test1);
 6             thread.start();
 7             console.writeline($"主线程id{threadid}_main()");
 8             console.read();
 9         }
10 
11         /// <summary>
12         /// 测试方法
13         /// </summary>
14         private static void test1()
15         {
16             //获取线程id
17             var threadid = thread.currentthread.managedthreadid;
18             console.writeline($"辅线程id{threadid}_test()");
19             for (int i = 0; i < 10; i++)
20             {
21                 thread.sleep(1000);//单位毫秒
22                 console.writeline($"辅线程id{threadid}_{datetime.now}");
23             }
24         }

结果:

 

 

 3、线程合并

thread.join操作会阻塞当前线程,等待子线程完成后再进行运行。

 1         static void main()
 2         {
 3             //获取线程id
 4             var threadid = thread.currentthread.managedthreadid;
 5             var thread = new thread(test1);
 6             thread.start();
 7             console.writeline($"主线程id{threadid}_main()1");
 8             thread.join();
 9             console.writeline($"主线程id{threadid}_main()2");
10             console.read();
11         }
12 
13         /// <summary>
14         /// 测试方法
15         /// </summary>
16         private static void test1()
17         {
18             //获取线程id
19             var threadid = thread.currentthread.managedthreadid;
20             console.writeline($"辅线程id{threadid}_test()");
21             for (int i = 0; i < 10; i++)
22             {
23                 thread.sleep(1000);//单位毫秒
24                 console.writeline($"辅线程id{threadid}_{datetime.now}");
25             }
26         }

结果:

 

 

 4、线程终止

 1         static void main()
 2         {
 3             //获取线程id
 4             var threadid = thread.currentthread.managedthreadid;
 5             var thread = new thread(test1);
 6             thread.start();
 7             console.writeline($"主线程id{threadid}_main()1");
 8             thread.sleep(3000);
 9            thread.abort();
10             console.writeline($"主线程id{threadid}_main()2");
11             console.read();
12         }
13 
14         /// <summary>
15         /// 测试方法
16         /// </summary>
17         private static void test1()
18         {
19             //获取线程id
20             var threadid = thread.currentthread.managedthreadid;
21             console.writeline($"辅线程id{threadid}_test()");
22             for (int i = 0; i < 10; i++)
23             {
24                 thread.sleep(1000);//单位毫秒
25                 console.writeline($"辅线程id{threadid}_{datetime.now}");
26             }
27         }

结果:

 5、线程中的参数传递

 1 static void main()
 2         {
 3             //获取线程id
 4             var threadid = thread.currentthread.managedthreadid;
 5             console.writeline($"主线程id{threadid}_main()");
 6             //第一种参数传递方式
 7             var thread1 = new thread(() => test1("小魔王"));
 8             thread1.start();
 9 
10             //第二种参数传递方式(参数只能是一个,object类型)
11             var parameterizedthreadstart = new parameterizedthreadstart(test2);
12             var thread2 = new thread(parameterizedthreadstart);
13             thread2.start("大魔王");
14             console.read();
15         }
16 
17         /// <summary>
18         /// 测试方法
19         /// </summary>
20         private static void test1(string name)
21         {
22             //获取线程id
23             var threadid = thread.currentthread.managedthreadid;
24             console.writeline($"辅线程id{threadid}_我的名字叫:{name}");
25         }
26 
27         /// <summary>
28         /// 测试方法
29         /// </summary>
30         private static void test2(object name)
31         {
32             //获取线程id
33             var threadid = thread.currentthread.managedthreadid;
34             console.writeline($"辅线程id{threadid}_我的名字叫:{name}");
35         }

结果:

 

 

 还有其他的传递方式,在此先不做说明了,这里只介绍thread提供的这么几种。

6、线程安全和线程锁lock

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。线程安全情况下,不会出现数据不一致或者数据污染的问题。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据! 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

lock 关键字通过获取指定对象的互斥锁,将语句块标记为临界区,执行语句然后释放该锁。

lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。使用lock,会导致整个应用程序串行化,降低程序的并发能力,影响性能。

到底什么场景下要使用lock保证线程安全:该串行就串行,该并行就并行。

加锁前:

 1  public static int i = 1000000;
 2         static void main()
 3         {
 4             //获取线程id
 5             var threadid = thread.currentthread.managedthreadid;
 6             for (int j = 0; j < 2; j++)
 7             {
 8                 var thread = new thread(test1);
 9                 thread.start();
10             }
11             console.read();
12         }
13 
14         /// <summary>
15         /// 测试方法
16         /// </summary>
17         private static void test1()
18         {
19             //获取线程id
20             var threadid = thread.currentthread.managedthreadid;
21            
22             console.writeline($"辅线程id{threadid}_i初始值:{i}");
23             int count = 0;
24             for (int j = 0; j < 1000000; j++)
25             {
26                 i--;
27                 count++;
28             }
29             console.writeline($"辅线程id{threadid}_运行次数:{count}");
30             console.writeline($"辅线程id{threadid}_i结束值:{i}");
31         }

结果:

 

 

 

加锁后:

 1  public static int i = 1000000;
 2         private readonly static object objlock = new object();
 3         static void main()
 4         {
 5             //获取线程id
 6             var threadid = thread.currentthread.managedthreadid;
 7             for (int j = 0; j < 2; j++)
 8             {
 9                 var thread = new thread(test1);
10                 thread.start();
11             }
12             console.read();
13         }
14 
15         private static void test1()
16         {
17             //获取线程id
18             var threadid = thread.currentthread.managedthreadid;
19            
20             int count = 0;
21             lock (objlock)
22             {
23                 console.writeline($"辅线程id{threadid}_i初始值:{i}");
24                 for (int j = 0; j < 1000000; j++)
25                 {
26                     i--;
27                     count++;
28                 }
29             }
30             console.writeline($"辅线程id{threadid}_运行次数:{count}");
31             console.writeline($"辅线程id{threadid}_i结束值:{i}");
32         }

结果:

 

好啦,今天关于线程的知识就分箱到这里啦。

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网