多线程实战(一) 线程基础

线程的好处,我想都不必多说,博客园太多了;但个人对线程了解还比较基础,决定把学习线程记录下来(有一些例子来之博客园):

创建线程

暂停线程

等待线程

线程传参数

lock

Monitor

创建线程

Thread t = new Thread(PrintNumbers);//线程创建
t.Start();//开始线程PrintNumbers();

static void PrintNumbers()
{
    Console.WriteLine("Starting...");
    for (int i = 1; i < 10; i++)
    {
    Console.WriteLine(i);
    }
}

暂停线程

sleep暂停线程;

Thread t = new Thread(PrintNumbersWithDelay);
            t.Start();

static void PrintNumbersWithDelay()
        {
            Console.WriteLine("Starting...");
            for (int i = 1; i < 10; i++)
            {
                Thread.Sleep(2000);
                Console.WriteLine(string.Format("顺序{0},时间:{1}", i, DateTime.Now));
            }
        }

sleep(2000);每隔2秒输出一次;

等待线程

  Thread t = new Thread(Run);

        t.Start();

        //Join相当于把Run方法内嵌如此
        t.Join();

        //该死的t.Join(),害的我主线程必须在你执行完后才能执行。
        Console.WriteLine("我是主线程:" + Thread.CurrentThread.GetHashCode());
    }

    static void Run()
    {
        //等待5s
        Thread.Sleep(5000);

        Console.WriteLine("我是线程:" + Thread.CurrentThread.GetHashCode());
    }

线程传参数

 var threadOne = new Thread(One);
            threadOne.Start("one");
            threadOne.Join();
            var threadTwo = new Thread(() => One("two"));
            threadTwo.Start();
            threadTwo.Join();
            var value = "three";
            var threadThree = new Thread(() => One(value));
            value = "four";
            var threadFour = new Thread(() => One(value));
            threadThree.Start();
            threadFour.Start();

static void One(object obj)
        {
            Console.WriteLine(obj);
        }

在启动线程3,4时,变量value的值变成four,最后打印出four

lock

Console.WriteLine("不规则统计");
            var c = new Counter();
            var t1 = new Thread(() => TestCounter(c));
            var t2 = new Thread(() => TestCounter(c));
            var t3 = new Thread(() => TestCounter(c));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine("总计: {0}",c.Count);
            Console.WriteLine("--------------------------");
            Console.WriteLine("正确统计");
            var c1 = new CounterWithLock();
            t1 = new Thread(() => TestCounter(c1));
            t2 = new Thread(() => TestCounter(c1));
            t3 = new Thread(() => TestCounter(c1));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine("总计: {0}", c1.Count);

static void TestCounter(CounterBase c)
        {
            for (int i = 0; i < 100000; i++)
            {
                c.Increment();
                c.Decrement();
            }
        }

        class Counter : CounterBase
        {
            public int Count { get; private set; }

            public override void Increment()
            {
                Count++;
            }

            public override void Decrement()
            {
                Count--;
            }
        }

        class CounterWithLock : CounterBase
        {
            private readonly object _syncRoot = new Object();

            public int Count { get; private set; }

            public override void Increment()
            {
                lock (_syncRoot)
                {
                    Count++;
                }
            }

            public override void Decrement()
            {
                lock (_syncRoot)
                {
                    Count--;
                }
            }
        }

        abstract class CounterBase
        {
            public abstract void Increment();

            public abstract void Decrement();
        }

加了锁和不加锁统计的结果完全不一样

Monitor

同步访问对象机制;在锁定的临界区中只允许让一个线程访问,其他线程排队等待。

1:Monitor.Enter和Monitor.Exit

 for (int i = 0; i < 10; i++)
            {
                Thread t = new Thread(Run);

                t.Start();
            }

//资源
        static object obj = new object();

        static int count = 0;

        static void Run()
        {
            Thread.Sleep(10);

            //进入临界区
            Monitor.Enter(obj);

            Console.WriteLine("当前数字:{0}", ++count);

            //退出临界区
            Monitor.Exit(obj);
        }

2:Monitor.Wait和Monitor.Pulse

Wait: 暂时的释放资源锁,然后该线程进入”等待队列“中,那么自然别的线程就能获取到资源锁。

Pulse:  唤醒“等待队列”中的线程,那么当时被Wait的线程就重新获取到了锁。

 public class Program
    {
        public static void Main(string[] args)
        {
            LockObj obj = new LockObj();

            //注意,这里使用的是同一个资源对象obj
            Jack jack = new Jack(obj);
            John john = new John(obj);

            Thread t1 = new Thread(new ThreadStart(jack.Run));
            Thread t2 = new Thread(new ThreadStart(john.Run));

            t1.Start();
            t1.Name = "Jack";

            t2.Start();
            t2.Name = "John";

            Console.ReadLine();
        }
    }

    //锁定对象
    public class LockObj { }

    public class Jack
    {
        private LockObj obj;

        public Jack(LockObj obj)
        {
            this.obj = obj;
        }

        public void Run()
        {
            Monitor.Enter(this.obj);

            Console.WriteLine("{0}:我已进入茅厕。", Thread.CurrentThread.Name);

            Console.WriteLine("{0}:擦,太臭了,我还是撤!", Thread.CurrentThread.Name);

            //暂时的释放锁资源
            Monitor.Wait(this.obj);

            Console.WriteLine("{0}:兄弟说的对,我还是进去吧。", Thread.CurrentThread.Name);

            //唤醒等待队列中的线程
            Monitor.Pulse(this.obj);

            Console.WriteLine("{0}:拉完了,真舒服。", Thread.CurrentThread.Name);

            Monitor.Exit(this.obj);
        }
    }

    public class John
    {
        private LockObj obj;

        public John(LockObj obj)
        {
            this.obj = obj;
        }

        public void Run()
        {
            Monitor.Enter(this.obj);

            Console.WriteLine("{0}:直奔茅厕,兄弟,你还是进来吧,小心憋坏了!",
                               Thread.CurrentThread.Name);

            //唤醒等待队列中的线程
            Monitor.Pulse(this.obj);

            Console.WriteLine("{0}:哗啦啦....", Thread.CurrentThread.Name);

            //暂时的释放锁资源
            Monitor.Wait(this.obj);

            Console.WriteLine("{0}:拉完了,真舒服。", Thread.CurrentThread.Name);

            Monitor.Exit(this.obj);
        }
    }

时间: 2024-10-12 20:57:57

多线程实战(一) 线程基础的相关文章

linux_c 开发(6-1)多线程程序设计_线程基础

多线程 线程(thread)技术早在60年代就被提出来了,但真正应用多线程到操作系统中去,实在80年代中期,solaris是这方面的佼佼者.传统的UNIX也支持线程的概念,但是在一个进程中只允许有一个线程,这样多线程就意味着多进程.现在多线程技术已经被许多操作系统所支持,包括Windows/NT.Linux. 优点: 和进程相比,它是一种非常"节俭"的多任务操作方式.在linux系统下,启动一个新的进程必须分配给他独立的空间地址,建立众多的数据表来维护他的代码段.堆栈段和数据段,这是一

多线程编程之线程基础

前言 此内容是阅读了书籍<JAVA多线程编程核心技术>后作为学习总结的文章,同时也梳理一下内容.建议大家有兴趣都可以阅读一下这本书,对于想了解更多的同学来说是一个很好的教材,同时建议大家多去思考和动手编写代码,融会贯通之后再去看一遍,会有更多的体会.就比如<JVM底层实现最佳实战>的书籍一样,我读了已经不下五遍了,但每次读都能有新的收获一样.希望对大家有帮助. 该篇文章是用于了解多线程的一些基本概念.JDK支持多线程编程的类和方法,接口等. 1.1 进程与线程概念 什么是进程: 进

说说C# 多线程那些事-线程基础

我第一次接触“线程”的概念时,觉得它深奥难懂,看了好多本书,花了很长时间才领悟到它的真谛.现在我就以一个初学者的心态,把我所理解的“多线程”描述给大家.这一次是系列文章,比较完整的展示与线程相关的基本概念.希望对初学者有所帮助. 如果你是高手,请你别继续看,会浪费你宝贵的时间. 一.基本概念 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又是由多个线程所组成的. 什么是线程? 线程是程序中的一个执行流,每个线程都有自己的专有寄

Android多线程研究(1)——线程基础及源代码剖析

从今天起我们来看一下Android中的多线程的知识,Android入门easy,可是要完毕一个完好的产品却不easy,让我们从线程開始一步步深入Android内部. 一.线程基础回想 package com.maso.test; public class TraditionalThread { public static void main(String[] args) { /* * 线程的第一种创建方式 */ Thread thread1 = new Thread(){ @Override p

Android多线程研究(1)——线程基础及源码剖析

从今天起我们来看一下Android中的多线程的知识,Android入门容易,但是要完成一个完善的产品却不容易,让我们从线程开始一步步深入Android内部. 一.线程基础回顾 package com.maso.test; public class TraditionalThread { public static void main(String[] args) { /* * 线程的第一种创建方式 */ Thread thread1 = new Thread(){ @Override publi

java核心技术-多线程之线程基础

说起线程,无法免俗首先要弄清楚的三个概念就是:进程.线程.协程.OK,那什么是进程,什么是线程,哪协程又是啥东西.进程:进程可以简单的理解为运行在操作系统中的程序,程序时静态代码,进程是动态运行着的代码,程序的运行需要向操作系统申请资源比如内存,文件句柄等,特别强调的是进程申请的资源都是独立的,也就是进程与进程之间资源是独立的.它被操作系统调度,所以进程是相对于操作系统的:线程:线程是进程中程序执行任务的那个,它共享着进程申请的资源:协程:可以简单的说是线程制造的轻量线程.讲完了基本的概念看看三

线程基础知识系列(三)线程的同步

本文是系列的第三篇,前面2篇,主要是针对单个线程如何管理,启动等,没有过多涉及多个线程是如何协同工作的. 线程基础知识系列(二)线程的管理 :线程的状态,控制,休眠,Interrupt,yield等 线程基础知识系列(一)线程的创建和启动  :线程的创建和启动,join(),daemon线程,Callable任务. 本文的主要内容 何谓线程安全? 何谓共享可变变量? 认识synchronized关键字 认识Lock synchronized vs Lock 1.何谓线程安全 多线程是把双刃剑,带

[Java聊天室服务器]实战之四 线程类

前言 学习任何一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列虽然涉及的是socket相关的知识,但学习之前,更想和广大程序员分享的是一种心境:学习是一个循序渐进的过程,心态应该随时调节,保持戒骄戒躁的状态.比如最近在看网易公开课MIT<算法导论>,老师提到,学习算法之前要计算机数学+离散数学+概率论等课程的知识,所以一直学不好算法的程序员不妨从基础入手,这都是中国式教育惹的祸啊!(此处省略一万字......)

线程基础知识系列(四)线程的同步2 线程通信和Condition变量

本文是系列的第四篇. 线程基础知识系列(三)线程的同步  :同步控制,锁及synchronized 线程基础知识系列(二)线程的管理 :线程的状态,控制,休眠,Interrupt,yield等 线程基础知识系列(一)线程的创建和启动  :线程的创建和启动,join(),daemon线程,Callable任务. 第三篇文章,重点阐述了如何使用锁和同步块对线程间共享可变变量保护,保证只有一个线程可以进入临界区.其实,没有过多的涉及另一个重要的同步概念:线程协作.第三篇中涉及的线程间并没有有效的协调.

线程基础知识

什么是线程: 在一个程序里的一个执行路线就叫做线程(thread).更准确的定义是:线程是"一个进程内部的控制序列" 一切进程至少都有一个执行线程 进程与线程 进程是资源竞争的基本单位 线程是程序执行的最小单位 线程共享进程数据,但也拥有自己的一部分数据 线程ID 一组寄存器 栈 errno 信号状态 优先级 fork和创建新线程的区别 当一个进程执行一个fork调用的时候,会创建出进程的一个新拷贝,新进程将拥有它自己的变量和它自己的PID.这个新进程的运行时间是独立的,它在执行时几乎