Shared List3 As New List(Of Integer)(System.Linq.Enumerable.Range(1, 1001))
Shared List4 As New List(Of Integer)
Shared List5 As New List(Of Integer)
Shared Sub MySub1()
For index As Integer = 0 To 1000
List4.Add(List3.MyFunc(index))
Next
End Sub
Shared Sub MySub2()
For index = 0 To 1000
List5.Add(List3.MyFunc(index))
Next
End Sub
多个线程同时读取同一个List3集合时为什么不发生争抢和死销及冲突呢。
只要写入操作时才发生呢。
------解决思路----------------------
读不改变状态,线程在任何地方打断、再恢复,没有任何问题,无需控制,所以没有冲突。
写会改变状态,比如线程在遍历节点时,正好遍历完第3个将要遍历第4个的时候中断了,恢复过来后:可能第2个位置插入了一个节点,原第3变成了第4,那么继续遍历等于将原第3重新遍历了一次;也可能第2个位置删除了一个节点,原第4变成了第3,那么继续遍历等于将原第4漏过了遍历……
各种情况太复杂,所以只要有了变动,就认为有冲突出错。
------解决思路----------------------
多线程并发写一块内存不是会出现内存错误,而是由于执行顺序不可控导致的结果不确定。比如n个线程并发对一个int变量做自增操作,并不会有任何异常,只是因为没有同步,导致最终结果可能不是n个顺序操作的累加。把这种现象叫做“内存错误”不太合适。
单纯对内存的读写比较简单,但是往往我们不是直接读写内存,而是使用一些类间接的读写,这时候就会涉及类的内部状态,情况更复杂点。
能够说是错误的是对不是线程安全的方法进行并发调用,导致所在类的内部状态混乱,就可能出现异常或错误。理论上只要文档没有明确说明一个属性/方法是线程安全的,都不应该并发调用,无论是读还是写。有些类在读或者使用者认为是读的场景也会更新内部状态,这种并发读也可能导致异常或者错误。
所以是否能够并发读不能自己想当然,必须看文档。像List<T>是文档说明了"It is safe to perform multiple read operations on a List<T>, but issues can occur if the collection is modified while it’s being read.",所以仅仅对它并发读没有问题。