多线程总结一:基本概念
一.普通对象,线程对象,线程
普通对象:针对于线程对象而言的。到处可见普通对象,Person p = new Person();一个无头无脑的人就是一个普通对象。
线程对象:线程类的实例对象。我自己定义了一个线程类public class CheckThread extends Thread{...},然后CheckThread ct = new CheckThread(),ct就是线程对象。
线程:代码的一次执行过程。
从概念层面讲,普通对象和线程对象是实实在在的东西,线程是虚的东西。线程好比一条细线。把普通对象和线程对象上的方法串起来执行,得到想要的结果而已。
从内存层面讲,对象就是一块内存地址,里面有数据和运行方法。而线程就是这些方法的一次执行路径。
唯一觉得线程对象和线程有点关系的地方:线程对象定义了线程的一个入口(线程对象的run方法),就好像main方法开启了主线程的一个入口一样。
二.锁和同步
锁是针对对象或者类而言的。Java中每个对象都有一个内置锁。
同步的表现形式为在一个方法前加synchronized关键字,作用为同一时刻,只能有一个线程调用此方法,谁获得了对象锁或类锁,谁就能调用此方法。当程序运行到synchronized同步方法或代码块时才锁才起作用。
类锁:Xxx.class。同一时刻多个线程都想调用setName方法的时候,谁先拿到Xxx类的类锁,谁就能调用。
对象锁:this。
线程1对静态同步方法的调用用到类锁,线程2对非静态同步方法的调用用到对象锁,它们之间不会产生阻塞。
一个对象可以同步方法和非同步方法同时存在,线程对同步方法的调用需要获得锁,对非同步方法的调用不需要。
线程1在获得对象A的锁后,正在调用同步方法a,恰好线程2也想调用方法a,因为锁只有一把,所以线程2没法调用方法a,此时线程2进入锁池队列。直到线程1完成对方法a的调用(synchronized结束),释放锁,线程2才能做接下来的事情。
记住一句话:线程想要调用对象或类的同步方法,必须先获得对象或类的锁。
一.普通对象,线程对象,线程
普通对象:针对于线程对象而言的。到处可见普通对象,Person p = new Person();一个无头无脑的人就是一个普通对象。
线程对象:线程类的实例对象。我自己定义了一个线程类public class CheckThread extends Thread{...},然后CheckThread ct = new CheckThread(),ct就是线程对象。
线程:代码的一次执行过程。
从概念层面讲,普通对象和线程对象是实实在在的东西,线程是虚的东西。线程好比一条细线。把普通对象和线程对象上的方法串起来执行,得到想要的结果而已。
从内存层面讲,对象就是一块内存地址,里面有数据和运行方法。而线程就是这些方法的一次执行路径。
唯一觉得线程对象和线程有点关系的地方:线程对象定义了线程的一个入口(线程对象的run方法),就好像main方法开启了主线程的一个入口一样。
二.锁和同步
锁是针对对象或者类而言的。Java中每个对象都有一个内置锁。
同步的表现形式为在一个方法前加synchronized关键字,作用为同一时刻,只能有一个线程调用此方法,谁获得了对象锁或类锁,谁就能调用此方法。当程序运行到synchronized同步方法或代码块时才锁才起作用。
类锁:Xxx.class。同一时刻多个线程都想调用setName方法的时候,谁先拿到Xxx类的类锁,谁就能调用。
public static synchronized int setName(String name){
Xxx.name = name;
}
等价于
public static int setName(String name){
synchronized(Xxx.class){
Xxx.name = name;
}
}
对象锁:this。
public synchronized int getX() {
return x++;
}
等价于
public int getX() {
synchronized (this) {
return x;
}
}
线程1对静态同步方法的调用用到类锁,线程2对非静态同步方法的调用用到对象锁,它们之间不会产生阻塞。
一个对象可以同步方法和非同步方法同时存在,线程对同步方法的调用需要获得锁,对非同步方法的调用不需要。
线程1在获得对象A的锁后,正在调用同步方法a,恰好线程2也想调用方法a,因为锁只有一把,所以线程2没法调用方法a,此时线程2进入锁池队列。直到线程1完成对方法a的调用(synchronized结束),释放锁,线程2才能做接下来的事情。
记住一句话:线程想要调用对象或类的同步方法,必须先获得对象或类的锁。