zoukankan      html  css  js  c++  java
  • [.net 多线程]线程基础

    一、线程状态

    1.新建状态(New):
            当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码
         2.就绪状态(Runnable)

            一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

            处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。
        3.运行状态(Running)

            当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.
    4. 阻塞状态(Blocked)

            线程运行过程中,可能由于各种原因进入阻塞状态:
            1>线程通过调用sleep方法进入睡眠状态;
            2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
            3>线程试图得到一个锁,而该锁正被其他线程持有;
            4>线程在等待某个触发条件;
            ......          
            所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。
        5. 死亡状态(Dead)

            有两个原因会导致线程死亡:
            1) run方法正常退出而自然死亡,
            2) 一个未捕获的异常终止了run方法而使线程猝死。
            为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.

    二、线程同步方式

    a. 内核模式(kernel-mode)

    将等待的线程置为等阻塞状态。当线程处于阻塞状态时,只会占用尽可能少的CPU时间。但是会引入上下文切换,保存、切换、恢复线程。这需要消耗相当多的资源。只有在挂起很长时间时,这种策略才是值得的。

    b.用户模式(user-mode)

    让线程简单的等待较短的时间,而不是切换到阻塞状态。这样只会浪费较少的CPU时间,节省了上下文切换消耗的CPU时间。

    c.混合模式(hybrid)

    混合模式首先尝试使用用户模式等待,如果线程等待了足够长的时间,则会切换到阻塞状态以节省CPU资源,如SpinWait。

    三、作用域

    • lock的作用域

      Lock是只能在进程内锁,不能跨进程,内部走的是混合构造,先自旋再转成内核构造。

      【特殊】关于对type类型的锁,如下:

     1         public void Test()
     2         {
     3             //======Example 3=====
     4             Console.WriteLine(DateTime.Now);
     5             AppDomain appDomain1 = AppDomain.CreateDomain("AppDomain1");
     6             LockTest Worker1 = (LockTest)appDomain1.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "ConsoleApplication1.LockTest");
     7             Worker1.Run();
     8 
     9             AppDomain appDomain2 = AppDomain.CreateDomain("AppDomain2");
    10             LockTest Worker2 = (LockTest)appDomain2.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "ConsoleApplication1.LockTest");
    11             Worker2.Run();
    12         }
    13 
    14         /// <summary>
    15         /// 跨应用程序域边界或远程访问时需要继承MarshalByRefObject
    16         /// </summary>
    17         public class LockTest : MarshalByRefObject
    18         {
    19             public void Run()
    20             {
    21                 lock (typeof(int))
    22                 {
    23                     Thread.Sleep(10000);
    24                     Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + ": Thread 释放," + DateTime.Now);
    25                 }
    26             }
    27         }
    lock(Type)跨域

     

  • 相关阅读:
    POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)
    LCA 最近公共祖先 (模板)
    线段树,最大值查询位置
    带权并查集
    转负二进制
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    UVALive 3295 Counting Triangles
    POJ 2752 Seek the Name, Seek the Fame (KMP)
    UVA 11584 Partitioning by Palindromes (字符串区间dp)
  • 原文地址:https://www.cnblogs.com/deepminer/p/8994918.html
Copyright © 2011-2022 走看看