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();
}

时间: 2024-08-03 06:58:22

C#多线程学习笔记的相关文章

Win32 多线程学习笔记

学到的API函数 一.线程 创建线程.结束线程.获取线程的结束码 CreateThread ExitThread GetExitCodeThread 二.线程结束时触发 创建线程之后,等待线程的结束之后,再继续执行 WaitForSingleObject 创建多个线程之后,等待一组线程(或其中的一个)结束,再继续执行 WaitForMultipleObjects 将消息循环与内核对象的等待合并 MsgWaitForMultipleObjects 三.同步 SendMessage 是同步的 Pos

Java多线程学习笔记--生产消费者模式

实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前水平只能膜拜,本次只能算学习笔记,为了巩固自己对Java多线程常规知识点的理解,路过大神还望能指导指导.下面一段代码是最常规的生产者消费者的例子: package com.zhanglei.demo; import java.util.ArrayList; import java.util.List

Java 多线程学习笔记:生产者消费者问题

前言:最近在学习Java多线程,看到ImportNew网上有网友翻译的一篇文章<阻塞队列实现生产者消费者模式>.在文中,使用的是Java的concurrent包中的阻塞队列来实现.在看完后,自行实现阻塞队列. (一)准备 在多线程中,生产者-消费者问题是一个经典的多线程同步问题.简单来说就是有两种线程(在这里也可以做进程理解)——生产者和消费者,他们共享一个固定大小的缓存区(如一个队列).生产者负责产生放入新数据,消费者负责取出缓存区的数据.具体介绍请参考 Producer-consumer

Java多线程学习笔记——从Java JVM对多线程数据同步的一些理解

   我们知道在多线程编程中,我们很大的一部分内容是为了解决线程间的资源同步问题和线程间共同协作解决问题.线程间的同步,通俗我们理解为僧多粥少,在粥有限情况下,我们怎么去防止大家有秩序的喝到粥,不至于哄抢都没得喝.线程讲协作,我们可以理解为我们在医院看病的时候,我们要先挂号,才能看病.现在医院有很多病人排队,怎么协调病人都有秩序的先挂号,后看病.本篇文章的重点不在此,也不是在此一下子能分析完,我们先从Java JVM的角度来理解多线程的一些方面. 我们知道多线程间的数据同步,我们是通过加锁的操作

Thinking in Java--Java多线程学习笔记(1)

这几天开始学习java多线程并发编程的内容了,以前也学习过多线程的知识,但是总是觉得学的不是很清楚:希望这一次学习<java编程思想>能让自己对并发,多线程的概念有一个更加深入的了解.这一章估计要写好几篇博客了,这篇博客是对于基础的一个总结,主要内容是对启动一个线程的几种方式和对线程一些操作函数的总结. 首先来了解一下多线程的概念,多线程看起来同一时刻在同时运行多个任务,但是从操作系统的层面来讲只是让多个任务以极快的速度进行切换而已,一个时刻实际上还是只有一个任务在cpu上运行的.Java中的

java多线程学习笔记——简单

进程:程序(任务)的执行过程——动态性. 持有资源(共享内存,共享文件)和线程. 线程:线程是系统中最小的执行单元,统一进程中有多个线程,线程共享进程的资源. 线程交互:互斥与同步. 注意:多线程是异步的,所以千万不要把Eclipse里代码的顺序当成线程执行的顺序,线程被调用的时机是随机的. java对线程的支持: class Thread    interface Runnable    共同的run方法 线程的创建和启动: 线程常用方法: 如何停止线程: java中有三种方法可以终止正在运行

java多线程学习笔记

一.线程的创建 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过实现Runnable接口,实例化Thread类 但是在使用Runnable定义的子类中没有start()方法,只有Thread类中才有.此时观察Thread类,有一个构造方法:public Thread(Runnable targer)此构造方法接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现的多线程.(start()可以协调系统的资源)

Java多线程学习笔记(一)

一 概述 一个进程只有一个至少会运行一个线程,Java中同样存在这样,在调用main方法的时候,线程又JVM所创建. 1 package link.summer7c.test; 2 3 public class Test{ 4 public static void main(String[] args){ 5 System.out.println(Thread.currentThread().getName()); 6 } 7 } 运行结果:main 叫做main的线程正在执行main()方法中

多线程学习笔记二

单例设计模式与多线程: 设计模式:对问题行之有效的解决方式.其实是一种思想. 单例设计模式: 解决的问题:可以保证一个类在内存中的对象唯一性. 比如对于多个程序使用同一个配置信息对象时,都需要保证对象的唯一性. 如果保证唯一性? 1.不允许其他程序用new创建该类对象. 2.在该类中创建一个本类实例. 3.对外提供一个方法,让其他程序可以获取对象. 实现步骤: 1.私有化该类的构造函数. 2.通过new在本类中创建一个本类对象. 3.定义一个共有的方法,将创建的对象返回. class Singl