1. 进程和线程的区别
1.1.进程是计算机分配资源的最小单位,一个进程代表一个任务,进程会创建一个线程来执行这个任务并给线程分配资源
1.2线程是计算机最小的执行单位
1.3 当我们执行一个Java程序时,会开启一个java.exe的进程,该进程会创建一个线程main线程(主线程),之后若有需要,该主线程会接着创建另一个线程,每个线程都有能力创建其他线程,而进程只需要创建主线程
2.线程的六种状态
- 新建(new)
- 执行(runnable)
- 阻塞(blocked)
- 等待(waiting)
- 定时等待(timed-waiting)
- 终止(terminated)
3.线程中的锁synchronized
3.1 synchronized(互斥锁)
应用场景:当多个线程同时在同一进程中运行时,有可能会发生线程干扰和内存不一致的问题,比如当A线程对某个静态变量static int number=0;++number;
操作时,而这时线程B也执行++number;
但是这个操作基本上属于同时操作的,按我们想的number应该的值该为2,但是由于B线程得到的number初始值为0,所以相当于重复了线程A的操作,于是就出现了线程干扰问题。可是当我们给线程A B加上锁并且分配同一把钥匙时,如synchronized(A.class){ ++number }
,就可以解决这个问题。
3.2 Lock锁
3.2.1 Lock锁跟synchronized的作用是差不多的,都是为某个线程加锁,synchronized是默认的实现加锁的功能,而Lock则是让你手动实现这些功能,相当于操作空间更大。
3.2.2 Lock中有一些方法配合使用来实现锁这个功能:
lock()方法获取锁,若获取锁失败,则变为等待状态
trylock()方法尝试获取锁,若失败,则推出线程状态队列
unlock()方法和lock()方法配合使用,用来释放当前线程的锁
3.2.3 Condition类中有两个方法可以和Lock类配合使用
await()方法让当前线程进入等待状态,并且不能自己结束等待状态
singal()方法随机唤醒一个等待中的线程
singalAll()方法唤醒唤醒所有等待线程
4高并发的解决方案
1.将加锁的粒度变小(加锁的代码尽量少)
2.对于读多写少的代码 采用读写锁
3.可以采用乐观锁(本质没有加锁,采用比对版本号的方式判断是否为同一线程)