多线程的高并发编程提高了我们的CPU利用率及简化开发模式,但是又同时给我们带来了风险,使用不当就会有风险,那到底有什么风险?我们来看看

1,线程的安全性问题

假设,我现在编写了一个程序,来保存系统的访问量,如何实现呢?

很简单,我可以设置一个全局变量,然后,每次用户访问一次系统,我就自增1,那么这个程序应该是这样写的,如下:

public class System {

    private int count;

    public int getCount(){

        return count++;

    }

}

这段代码,大家觉得有没有问题?

如果在单线程的模式下,没问题,但是在多线程的模式下,会有问题,为什么?

因为其中一个关键的步骤,count++不是一个原子操作,这个操作实际会分为三个步骤,

分别是,读取count值,给count值+1,将结果写到count值上。

那么大家想想,当我们有多个线程同时访问这个资源的时候,会出现什么情况?

高并发编程-03-并发编程存在的风险_多线程

这就是我们说的线程安全问题。

如果解决此类问题,java给我们提供一种同步机制,你只需要这么做就可以解决问题:

public synchronized int getCount(){

    return count++;

}

好了,接下来,我们来说会出现的第二类问题

2,活跃性问题

比如,死锁,饥饿,活锁,这些都是属于活跃性问题。当某个操作无法继续执行时,这就是活跃性问题,我举个死锁的例子,比如我老婆跟我分工家务活,要求我先拖地,她就洗碗,而我要求她先洗碗,我再拖地,那么这个时候,我们彼此手握对方进行下一步工作的开启条件,但都彼此不愿意先动手,于是就陷入了僵局,这就是死锁。

换成程序的说法,就是A线程需要等待的锁被B线程占用,而B线程需要的等待的锁被A线程占用,所以相互都不释放,于是就陷入了死锁。

更多问题,我们后续继续讲解

3,性能问题

性能问题,你肯定会有疑问,多线程不就是为了提高系统的吞吐量吗?怎么还有性能问题?

这个原因很简单,还是那句话,你没有正确使用

下面我们来看看多线程可能带来的性能问题有哪些?

当我们采用多线程编程时,每个线程会由CPU实现调度,分配一定的时间片,那这个时候,调度器就会频繁挂起一个活跃的线程转而运行另一个线程,这就是我们说的“上下文切换”,这种操作将会带来极大的开销。

还有一个问题,当CPU重新切换回之前活跃的线程时,线程是否要继续之前未完成的操作,答案是必须的,那么就需要做一件事,在CPU切换的时候,保存线程的执行状态,这又是一笔开销。

最后,还有一种情况,就是多线程共享有状态的数据时,需要使用同步机制来保证数据安全,而这些机制会抑制编译器的某些优化,比如使得内存缓冲区中的数据失效等等,以及增加共享内存总线的同步流量

所以,有个重要的问题,一般我们的程序开启多少线程合适?

当然不是越多越好,大家可以留言,说说你的答案