线程处理的问题:
1.非原子操作
原子操作指一个操作要么尚未开始,要么已经完成;而非原子操作则有可能出现中间态,即部分完成的情况。c#语音通常认为所以操作都是非原子性的,在多线程环境中,操作的非原子性可能会造成竞态条件。
2.竞态条件
当两个线程同时访问一个对象时,无法预测哪个线程先执行,哪个线程后执行,两者的执行顺序取决于上下文切换机制,操作系统会在它认为合适的时机切换线程,但不能保证每次的执行顺序都是一样。
因此,多线程代码的质量主要依赖于编程水平、专门的代码分析工具以及长期的压力测试。
3.复杂的内存模型
现代处理器在使用一个内存中的变量时,会先将变量拷贝到处理器的高速缓存中,此后的计算使用缓存中的数据,再选择合适的时机去同步缓存与内存中的数据,这一机制主要是为了节省IO操作,提高计算效率。但是,如果多个处理器同时使用内存中的同一个变量,将会出现更加复杂的缓存数据同步问题,产生竞态条件
4.死锁
前面所述竞态条件的问题,可以使用lock机制来避免。lock机制允许为一部分代码加锁,一次只允许一个线程访问,其他线程都将被挂起,当线程完全执行完毕后释放锁,其他线程才可以继续访问,同时lock机制还能够正确处理缓存同步的问题。
如果不同的线程以不同的顺序来获取锁,就可能会产生死锁,例如:两个线程都需要获取锁A和锁B,一号线程先获取了锁A,二号线程先获取了锁B,此时,一号线程等待锁B释放,二号线程等待锁A释放,两个线程都被挂起,等待对方的锁释放,造成死锁。