一、为什么多线程环境不适合带有状态的对象?
这个问题更清晰一点是“在共享内存模型下,为什么多线程环境不适合带有状态的共享对象”,如果对象不贡献,是线程私有的,或者压根就不是共享内存,带状态都无所谓的。 但是一旦需要共享,由于多线程在执行对象方法修改状态时会在任意时间执行任意指令,导致程序的顺序性无法保证,造成bug。举个多线程入门都会知道的例子:
假设有一个计数的对象counter,类定义如下:
这个counter是多线程的共享对象,其中的getAndIncrement在各个线程里面实际执行的序列是:
long temp = value;
value = temp + 1;
return temp;每个thread都会去内存读取value然后在thread本地处理并写回,问题在于在一个thread执行这个sequence时,其他线程可能已经执行很多次了,假设value都已经变成4了,但是这个thread在读的时候还是1,这样一来写回2,把其他线程的结果都覆盖了,出现bug。问题的本质是这个读value,+1然后写回的操作sequence对于共享变量有大于1个的操作(这里是读写)且不是原子性的,也就是会有很多threads插入交织在任意时间执行任何一个step。
带状态的对象天然不是多线程安全的,应该能够说明这个问题了。
二、是不是意味着如果有多线程环境,最好慎用面向对象编程?
多线程环境下,只要是内存共享可修改的状态,无论什么范式都是一样的问题,跟是否面向对象无关。问题的关键在于多线程算是打破了对于cpu,内存的抽象,需要你对这些东西有一定的了解,才能写出线程安全且高效的程序,虽说常用的面向对象语言都自带了并发包,但也不是一股脑地加锁互斥同步就算的上OK,除了性能之外,还有死锁,饥饿等问题。
函数式编程以及某些并发模型,对写多线程程序是友好的,
三、自定义对象能否作为数据包传递从服务器到客户端?
可以,一般中间会有serDe,比如Json, xml, byte,hessian, pb等。
四、如果真的是这样,ooad时要考虑哪些方面呢?
并发问题跟你说的面向对象设计,java web,数据传输是不同层次的东西。有疑问的时候,一定要定位到问题是什么,对于你这几个问题,定位到你对并发是没有概念的,作为学生,你就可以去学习并发编程设计,写代码,验证(学的过程中自然会接触到相关的知识)。还有一个,问题里面提到了很多次面向对象设计,但凡是设计一定是有原则,以及基于这个原则下好的实践的总结(模式),锻炼自己面向对象设计能力时可以借鉴一下,有帮助。不过这些东西有一个共同的特点:不写点垃圾代码,感受不深:D。