class Test
{
  object o=new object();//锁标识
  void M(){
    lock(o){
      //A处:一些语句
    }
  }
  Thread M2(){
    Thread t=new Thread(this.M);
    return t;
  }
  void App(){
    Thread[] ts=new Thread[2];
    ts[0]=this.M2();
    ts[1]=this.M2();
    for(int i=0;i<ts.Length;i++){
       ts[i].Start();
    }
  }
}
执行App方法时 ts[i].Start();执行this.M1方法因为有lock所以在A处是不会挂起的
现在我想问,这个挂起是指 不会在执行中 存在ts[0]时有ts[1]出现或相反, 而操作系统的不同进程之间来看 它依然是会挂起的只是不出现 t[i]之间的 错乱,还是说 绝对的,操作系统所有进程都停下来等 某个ts[i]当它在执行lock段(A处)代码时我倾向于认为 lock只是起到 ts[i]之间不错乱执行 而不是上述的后面一种情况,全部停下来等它一个线程的在lock段的工作.这样来说如果lock段代码中的 值依然是 不保险的,除非是后一种情况大家认为呢,还是我的分析根本就是错的..

解决方案 »

  1.   

    lock(o){ 
          //A处:一些语句 
        } 
    A处的代码只能有一个线程执行。如果创建了2个线程t1、t2.当t1执行A处代码的时候,t2发现是被锁的,t2只能等待锁的解除。等到t1完成A处代码,t1释放了锁。t2就会执行。我是这么理解的。
      

  2.   

    按楼上的这样分析 其实 MSDN也是这么说的,只是保证对lock的锁定区里 执行是唯一的但这种唯一究竟指是原子的还是不是原子的,(我对原子的理解是 电脑CPU原子执行时 是绝对单一的)如果我在A处 有一个对象 X x=new X();中的x 与关于对这个x的一系列操作; 而这个X的定义是public class X{ public int i; public List<int> iis; }如果不是原子操作 那么当A处执行时,其它不经过 lock(o)锁的线程比如程序的默认主线程 他直接去改变了
    X.i;或X.iis中的值 操作了它们,在这个线程执行lock(o)段(A处代码)期间,那么 这个线程一样 出问题..为必然 是原子的?即lock锁定将导致原子的操作,那么也就是说如果A处很耗时,那整个操作系统都可能出现假死现象.. 是这样的吗?
      

  3.   

     public class ThreadLock
        {
            static void Main(string[] args)
            {
               for (int i = 0; i < 10; i++)
                {
                    test t = new test();
                    t.i = i;
                    Thread th = new Thread(t.M);               
                    th.Start();
                    t.SetJ();//操作了静态变量J成功。
                    t.SetI();//操作锁中使用的变量I失败
                    t.SetK();//操作锁外的变量K成功。
                }
                Console.WriteLine("主线程执行完毕");
                Console.ReadLine();
            }
        }
        public class test
        {
            public static int j;
            public int i;
            public int k;
            object o = new object();//锁标识 
            public void M()
            {
                lock (o)
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("我是第" + i.ToString() + "个线程,J="+j.ToString()+"K="+k.ToString());
                }
            }
            public void SetJ()
            {
                j++;
            }
            public void SetI()
            {
                i++;
            }
            public void SetK()
            {
                k++;
            } 执行结果如下
    主线程执行完毕
    我是第1个线程,J=10K=1
    我是第2个线程,J=10K=1
    我是第3个线程,J=10K=1
    我是第5个线程,J=10K=1
    我是第4个线程,J=10K=1
    我是第6个线程,J=10K=1
    我是第7个线程,J=10K=1
    我是第8个线程,J=10K=1
    我是第9个线程,J=10K=1
    我是第10个线程,J=10K=1
      

  4.   

    winform中测试。主线程未被锁。
      

  5.   

    谢谢: l8487 我觉得你看明白我问题的意思,不过嘛,我似乎没太看懂               t.SetJ();//操作了静态变量J成功。 
                    t.SetI();//操作锁中使用的变量I失败 
                    t.SetK();//操作锁外的变量K成功。这些注释是什么意思 
    从结果分析下
      

  6.   

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;namespace ConsoleApplication1 {
        public class ThreadLock {
            static void Main(string[] args) {
                for (int i = 0; i < 10; i++) {
                    test t = new test();
                    t.i = i;
                    Thread th = new Thread(t.M);
                    th.Start();
                    t.SetJ();//操作了静态变量J成功。 
                    t.SetI();//操作锁中使用的变量I失败 
                    t.SetK();//操作锁外的变量K成功。 
                }
                Console.WriteLine("主线程执行完毕");
                Console.ReadLine();
            }
        }
        public class test {
            public static int j;
            public int i;
            public int k;
            object o = new object();//锁标识 
            public void M() {
                lock (o) {
                    Thread.Sleep(2000);
                    Console.WriteLine("我是第" + i.ToString() + "个线程,J=" + j.ToString() + "K=" + k.ToString());
                }
            }
            public void SetJ() {
                j++;
            }
            public void SetI() {
                i++;
            }
            public void SetK() {
                k++;
            }    }
    }
    //上面是 完全可测试代码//结果上看 
    i 为1到10 不重复,但可能乱序;
    j 稳定的为10
    k 稳定的为1
               
      

  7.   

    哦。。j是static的。静态的。属于类,还不属于类的实例。每次执行j都+1.当主线程循环结束的时候,j=10了。。所有所有的线程都打印的j是10.。。
    i是线程中的变量。线程启动以后,修改new的实例中的i值。i值被修改成功。然后才打印I的。所以i也修改成功了。
      

  8.   

    我猜想 k=1的原因因为主线程先完,当主线程完时 因为 休眠2秒的原因 子线程组都还没开跑,这时 k=10
    然后 进入子线程 这时会依次序的进入 子线程,但 进入时 只能这么认为,线程上下文环境 尚在k=1的状况下所以 这时所有的k都出来相同的1
      

  9.   

    上述代码去掉 lock 的情况 结果特征也未见变化
      

  10.   

    哦不对,原因是你把 Test实例化了10次,每次你去某一个实例加1当然 k=1了