• 笔试题多线程


    1. 描述线程与进程的区别?

    • 一个应用程序实例是一个进程,一个进程内包含一个或多个线程,线程是进程的一部分;
    • 进程之间是相互独立的,他们有各自的私有内存空间和资源,进程内的线程可以共享其所属进程的所有资源;

    2. 为什么GUI不支持跨线程访问控件?一般如何解决这个问题?

    因为GUI应用程序引入了一个特殊的线程处理模型,为了保证UI控件的线程安全,这个线程处理模型不允许其他子线程跨线程访问UI元素。解决方法还是比较多的,如:

    • 利用UI控件提供的方法,Winform是控件的Invoke方法,WPF中是控件的Dispatcher.Invoke方法;
    • 使用BackgroundWorker;
    • 使用GUI线程处理模型的同步上下文SynchronizationContext来提交UI更新操作

    上面几个方式在文中已详细给出。

    3. 简述后台线程和前台线程的区别?

    应用程序必须运行完所有的前台线程才可以退出,或者主动结束前台线程,不管后台线程是否还在运行,应用程序都会结束;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。

    通过将 Thread.IsBackground 设置为 true,就可以将线程指定为后台线程,主线程就是一个前台线程。

    4. 说说常用的锁,lock是一种什么样的锁?

    常用的如如SemaphoreSlim、ManualResetEventSlim、Monitor、ReadWriteLockSlim,lock是一个混合锁,其实质是Monitor['mɒnɪtə]。

    5. lock为什么要锁定一个参数,可不可锁定一个值类型?这个参数有什么要求?

    lock的锁对象要求为一个引用类型。她可以锁定值类型,但值类型会被装箱,每次装箱后的对象都不一样,会导致锁定无效。

    对于lock锁,锁定的这个对象参数才是关键,这个参数的同步索引块指针会指向一个真正的锁(同步块),这个锁(同步块)会被复用。

    6. 多线程和异步有什么关系和区别?

    多线程是实现异步的主要方式之一,异步并不等同于多线程。实现异步的方式还有很多,比如利用硬件的特性、使用进程或纤程等。在.NET中就有很多的异步编程支持,比如很多地方都有Begin***、End***的方法,就是一种异步编程支持,她内部有些是利用多线程,有些是利用硬件的特性来实现的异步编程。

    7. 线程池的优点有哪些?又有哪些不足?

    优点:减小线程创建和销毁的开销,可以复用线程;也从而减少了线程上下文切换的性能损失;在GC回收时,较少的线程更有利于GC的回收效率。

    缺点:线程池无法对一个线程有更多的精确的控制,如了解其运行状态等;不能设置线程的优先级;加入到线程池的任务(方法)不能有返回值;对于需要长期运行的任务就不适合线程池。

    8. Mutex和lock有何不同?一般用哪一个作为锁使用更好?

    Mutex是一个基于内核模式的互斥锁,支持锁的递归调用,而Lock是一个混合锁,一般建议使用Lock更好,因为lock的性能更好。

    9. 下面的代码,调用方法DeadLockTest(20),是否会引起死锁?并说明理由。

    public void DeadLockTest(int i)
    {
        lock (this)   //或者lock一个静态object变量
        {
            if (i > 10)
            {
                Console.WriteLine(i--);
                DeadLockTest(i);
            }
        }
    }

    不会的,因为lock是一个混合锁,支持锁的递归调用,如果你使用一个ManualResetEvent或AutoResetEvent可能就会发生死锁。

    10. 用双检锁实现一个单例模式Singleton。

        public static class Singleton<T> where T : class,new()
        {
            private static T _Instance;
            private static object _lockObj = new object();
    
            /// <summary>
            /// 获取单例对象的实例
            /// </summary>
            public static T GetInstance()
            {
                if (_Instance != null) return _Instance;
                lock (_lockObj)
                {
                    if (_Instance == null)
                    {
                        var temp = Activator.CreateInstance<T>();
                        System.Threading.Interlocked.Exchange(ref _Instance, temp);
                    }
                }
                return _Instance;
            }
        }

    11.下面代码输出结果是什么?为什么?如何改进她?

    int a = 0;
    System.Threading.Tasks.Parallel.For(0, 100000, (i) =>
    {
        a++; 
    });
    Console.Write(a);

    输出结果不稳定,小于等于100000。因为多线程访问,没有使用锁机制,会导致有更新丢失。具体原因和改进在文中已经详细的给出了。

  • 相关阅读:
    (Lineup the Dominoes筛子)三维状压
    Halloween Costumes 玄学题
    jQuery之动画
    javascript之位置
    javascript之事件
    jQuery之DOM
    jQuery之选择器
    jQuery简介
    javascript之Bom简介
    javascript之DOM操作
  • 原文地址:https://www.cnblogs.com/fantaohaoyou/p/9390134.html
Copyright © 2020-2023  润新知