C#多线程学习笔记
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication19
{
class Program
{
//创建一个新线程
//static void Main(string[] args)
//{
// Thread t = new Thread(WriteY);//创建新线程
// t.Start();//启动新线程,执行writeY();
// for (int i = 0; i < 1000; i++) Console.Write("x");
// Console.ReadKey();
//}
//static void WriteY()
//{
// for (int i = 0; i < 1000; i++) Console.Write("y");
//}
/*
CLR 为每个线程分配各自独立的栈空间,因此局部变量是独立的。在下面的例子中,我们定义一个拥有局部变量的方法,
* 然后在主线程和新创建的线程中同时执行该方法。
*/
//static void Main(string[] args)
//{
// new Thread(Go).Start();
// Go();
// Console.ReadKey();
//}
//static void Go()
//{
// for (int i = 0; i < 5; i++)
// Console.Write('?');
//}
//线程可以通过对同一对象的引用来共享数据。
//由于两个线程是调用了同一个的ThreadTest实例上的Go(),它们共享了done字段
//,因此输出结果是一次 “ Done “,而不是两次。
//bool done;
//static void Main(string[] args)
//{
// Program tt = new Program();
// new Thread(tt.Go).Start();
// tt.Go();
// Console.ReadKey();
//}
//void Go()
//{
// if (!done) { done = true; Console.WriteLine("Done"); }
//}
//静态字段提供了另一种在线程间共享数据的方式,以下是一个静态的done字段的例子:
//static bool done;
//static void Main(string[] args)
//{
// new Thread(Go).Start();
// Go();
// Console.ReadKey();
//}
//static void Go()
//{
// if (!done) { done = true; Console.WriteLine("Done"); }
//}
/*
需要在读写公共字段时,获得一个排它锁(互斥锁,exclusive lock )。C# 提供了lock来达到这个目的:
* 当两个线程同时争夺一个锁的时候(例子中的locker),一个线程等待,或者说阻塞,直到锁变为可用。
* 这样就确保了在同一时刻只有一个线程能进入临界区(critical section,不允许并发执行的代码)
* ,所以 “ Done “ 只被打印了一次。像这种用来避免在多线程下的不确定性的方式被称为线程安全(thread-safe)。
*/
//static bool done;
//static readonly object locker = new object();
//static void Main(string[] args)
//{
// new Thread(Go).Start();
// Go();
// Console.ReadKey();
//}
//static void Go()
//{
// lock (locker)
// {
// if (!done) { Console.WriteLine("Done"); done = true; }
// }
//}
/*
可以通过调用线程的Join方法来等待另一个线程结束
当使用Sleep或Join等待时,线程是阻塞(blocked)状态,因此不会消耗 CPU 资源
Thread.Sleep(0)会立即释放当前的时间片,将 CPU 资源出让给其它线程。Framework 4.0 新的Thread.Yield()方法与其相同,除了它只会出让给运行在相同处理器核心上的其它线程。
Sleep(0)和Yield在调整代码性能时偶尔有用,它也是一个很好的诊断工具,
* 可以用于找出线程安全(thread safety)的问题。如果在你代码的任意位置插入Thread.Yield()会影响到程序
* ,基本可以确定存在 bug。
*/
//static void Main(string[] args)
//{
// Thread t = new Thread(Go);
// t.Start();
// t.Join();
// Thread.Sleep(TimeSpan.FromSeconds(1));
// Console.WriteLine("Thread t has ended");
// Console.ReadKey();
//}
//static void Go()
//{
// for (int i = 0; i < 1000; i++)
// Console.Write("y");
//}
/*使用Thread类的构造方法来创建线程,
通过传递ThreadStart委托来指明线程从哪里开始运行,
* 下面是ThreadStart委托的定义:
*/
//static void Go()
//{
// Console.WriteLine("hello!");
//}
//static void Main()
//{
// Thread t = new Thread( new ThreadStart(Go));
// t.Start();
// Go();
// Console.ReadKey();
//}
/*
另一个方法是向Thread的Start方法传递参数
*/
//static void Main()
//{
// Thread t = new Thread(Print);
// t.Start("Hello from t!");
// Console.ReadKey();
//}
//static void Print(object messageObj)
//{
// string message = (string)messageObj; // 需要强制类型转换
// Console.WriteLine(message);
//}
/*
每一个线程都有一个 Name 属性,我们可以设置它以便于调试
* 。这在 Visual Studio 中非常有用,因为线程的名字会显示在线程窗口(Threads Window)与调试位置(Debug Location)工具栏上。
* 线程的名字只能设置一次,以后尝试修改会抛出异常。
静态的Thread.CurrentThread属性会返回当前执行的线程。在下面的例子中,我们设置主线程的名字:
*/
//static void Main()
//{
// Thread.CurrentThread.Name = "main";
// Thread worker = new Thread(Go);
// worker.Name = "worker";
// worker.Start();
// Go();
// Console.ReadKey();
//}
//static void Go()
//{
// Console.WriteLine("hello from" + Thread.CurrentThread.Name);
//}
/*
默认情况下,显式创建的线程都是前台线程(foreground threads)。
* 只要有一个前台线程在运行,程序就可以保持存活,而后台线程(background threads)并不能保持程序存活。
* 当一个程序中所有前台线程停止运行时,
* 仍在运行的所有后台线程会被强制终止。
* 可以通过线程的IsBackground属性来查询或修改线程的前后台状态
在退出程序时可以显式的等待这些后台线程结束。有两种方法可以实现:
如果是自己创建的线程,在线程上调用Join方法。
如果是使用线程池线程,使用事件等待句柄。
* */
//static void Main(string[] args)
//{
// Thread worker = new Thread(() => Console.ReadLine());
// if (args.Length > 0) worker.IsBackground = true;
// worker.Start();
// Console.ReadKey();
//}
/*
如果是使用 .NET Framework 4.0 以前的版本,
* 则不能使用任务并行库。
* 你必须通过一种旧的构造使用线程池:ThreadPool.QueueUserWorkItem与异步委托。
* 这两者之间的不同在于异步委托可以让你从线程中返回数据,
* 同时异步委托还可以将异常封送回调用方。
*/
//static void main()
//{
// ThreadPool.QueueUserWorkItem(Go);
// ThreadPool.QueueUserWorkItem(Go, 123);
// Console.ReadKey();
//}
//static void Go(object data)
//{
// Console.WriteLine("hello form the thread pool!" + data);
//}
/*
要使用非泛型的Task类,调用Task.Factory.StartNew,并传递目标方法的委托:
*/
//static void Main()
//{
// Task.Factory.StartNew(Go);
// Console.ReadKey();
//}
//static void Go()
//{
// Console.WriteLine("Hello from thread pool!");
//}
//static void Main()
//{
// Func<string, int> method = Work;
// IAsyncResult cookie = method.BeginInvoke("test", null, null);
//
// 这里可以并行执行其它任务
//
//int result = method.EndInvoke(cookie);
//Console.WriteLine("String length is: " + result);
//Console.ReadKey();
//}
//static int Work(string s) { return s.Length; }
/*
下一步是同步(synchronization):为期望的结果协调线程的行为。当多个线程访问同一个数据时,同步尤其重要,但是这是一件非常容易搞砸的事情。
同步构造可以分为以下四类:
简单的阻塞方法
这些方法会使当前线程等待另一个线程结束或是自己等待一段时间。Sleep、Join与Task.Wait都是简单的阻塞方法。
锁构造
锁构造能够限制每次可以执行某些动作或是执行某段代码的线程数量。排它锁构造是最常见的,它每次只允许一个线程执行,从而可以使得参与竞争的线程在访问公共数据时不会彼此干扰。标准的排它锁构造是lock(Monitor.Enter/Monitor.Exit)、Mutex与 SpinLock。非排它锁构造是Semaphore、SemaphoreSlim以及读写锁。
信号构造
信号构造可以使一个线程暂停,直到接收到另一个线程的通知,避免了低效的轮询 。有两种经常使用的信号设施:事件等待句柄(event wait handle )和Monitor类的Wait / Pluse方法。Framework 4.0 加入了CountdownEvent与Barrier类。
非阻塞同步构造
非阻塞同步构造通过调用处理器指令来保护对公共字段的访问。CLR 与 C# 提供了下列非阻塞构造:Thread.MemoryBarrier 、Thread.VolatileRead、Thread.VolatileWrite、volatile关键字以及Interlocked类。
*/
}
//public delegate void ThreadStart();
}
C#多线程学习笔记的更多相关文章
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
- JAVA多线程学习笔记(1)
JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...
- 多线程学习笔记九之ThreadLocal
目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...
- java进阶-多线程学习笔记
多线程学习笔记 1.什么是线程 操作系统中 打开一个程序就是一个进程 一个进程可以创建多个线程 现在系统中 系统调度的最小单元是线程 2.多线程有什么用? 发挥多核CPU的优势 如果使用多线程 将计算 ...
- Java多线程学习笔记(一)——多线程实现和安全问题
1. 线程.进程.多线程: 进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天. 2.线程的特点: 1.运行任 ...
- java 多线程学习笔记
这篇文章主要是个人的学习笔记,是以例子来驱动的,加深自己对多线程的理解. 一:实现多线程的两种方法 1.继承Thread class MyThread1 extends Thread{ public ...
- Java多线程学习笔记--生产消费者模式
实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前 ...
- Java多线程学习笔记
进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...
- C# 多线程学习笔记 - 3
本文主要针对 GKarch 相关文章留作笔记,仅在原文基础上记录了自己的理解与摘抄部分片段. 遵循原作者的 CC 3.0 协议. 如果想要了解更加详细的文章信息内容,请访问下列地址进行学习. 原文章地 ...
- C# 多线程学习笔记 - 2
本文主要针对 GKarch 相关文章留作笔记,仅在原文基础上记录了自己的理解与摘抄部分片段. 遵循原作者的 CC 3.0 协议. 如果想要了解更加详细的文章信息内容,请访问下列地址进行学习. 原文章地 ...
随机推荐
- C#学习系列-.NET体系结构
.NET框架概述 .NET 框架为.NET应用程序运行提供虚拟机环境,为.NET应用程序提供编译.运行.内存管理.垃圾回收.安全等服务. .NET框架组成部分 1.公共语言运行时(Common L ...
- python2.7和python3共存
python2.7和python3共存 原本装了python,玩nodejs的时候需要node-gyp来编译依赖,无赖这货需要python2.5<v<3.0,那就弄两个版本吧 转载自 ht ...
- ajax获取json对象
ajax获取json对象 ajax获取json数据,都是一个原理,设置response 的Content-Type:application/json,这样浏览器自动会解析为json对象 $result ...
- 将 PAGE_VERIFY 数据库选项设置为 CHECKSUM
此规则检查 PAGE_VERIFY 数据库选项是否已设置为 CHECKSUM.为 PAGE_VERIFY 数据库选项启用 CHECKSUM 后,SQL Server 数据库引擎会在向磁盘中写入页面时计 ...
- Chrome开发者工具之JavaScript内存分析
阅读目录 对象大小(Object sizes) 对象的占用总内存树 支配对象(Dominators) V8介绍 Chrome 任务管理器 通过DevTools Timeline来定位内存问题 内存回收 ...
- CSS伪类与CSS伪元素的区别及由来
关于两者的区别,其实是很古老的问题.但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手.早些年刚入行的时候,我自己也被深深误导,因 ...
- 兼容90%标准C的词法分析器
不能分词八进制和数字类型加前/后缀的情况 拿这个词法分析器跑了一遍整个Nginx源码,基本都能正确的分出结果,后面有测试例子~ #ifndef _STATES_H_ #define _STATES_H ...
- 深入理解CSS绝对定位
× 目录 [1]定义 [2]特性 [3]display[4]clip[5]静态位置[6]overflow 前面的话 前面已经介绍了定位的偏移和层叠,例子中大量的应用了绝对定位.因为相较于相对定位和固定 ...
- initial、inherit、unset、revert和all
前面的话 在CSS中,有4个关键字理论上可以应用于任何的CSS属性,它们是initial(初始).inherit(继承).unset(未设置).revert(还原).而all的取值只能是以上这4个关键 ...
- 信息加密之Base64
Base64是一种最简单的简单的加密形式,经常被使用,记录一下,以便日后可以深入了解. jdk格式: //获得密钥Base64Encoder encoder = new Base64Encoder() ...