1.引言
最近面试,遇到锁相关的考点,以前学习过可惜忘记了,而且随着工作年限的增长,很多以前搞不懂的,再次理解变得简单,看来有必要看看以前的书了
2.正题
2.1 程序的三要素
- 原子性
原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。及时在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰。
int a = 10; //原子操作一个指令 赋值
a++; //2非原子操作,取值,值加1,赋值
int b=a; //3 非原子操作,取值,赋值
a = a+1; //4 非原子操作,取值,加1,赋值
可见性
可见性是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改,java中用volatile关键字来保证变量的可见性,volatile只能保证可见性 并不能保证有序性有序性
有序性就是程序执行的顺序按照代码的先后顺序执行,java中用** sychronized**保证有序性
2.2 sychronized
sychronized 保证原子性和有序性,有以下 三种用法:
public class ThreadTest {
public synchronized void meathondA() {
System.out.println("方法A end"); // 方式1
}
public void meathondA1() {
synchronized (this) {
System.out.println("方法A end");// 方式2
}
}
public void meathondA2() {
synchronized (ThreadTest.class) {
System.out.println("方法A end");// 方式3
}
}
}
其中方式1 和方式2一样效果,方式3 与方式1,2 不同。
多线程的本质就是:多线程访问公共变量,我的理解分俩种情况。
- 多线程持有同一个对象,对这个对象的非静态公共变量进行改变
public class VolatileTest {
public int as = 0;
public static void main(String[] args) {
VolatileTest m = new VolatileTest();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int n = 0; n < 1000; n++) {
m.increase();
}
}
});
thread.start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(m.as);
}
public synchronized void increase() {
as++;//取值,加1,赋值
}
}
输出结果10000
或者这样写
public class VolatileTest {
public int as = 0;
public static void main(String[] args) {
VolatileTest m = new VolatileTest();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (m) {
for (int n = 0; n < 1000; n++) {
m.increase();
}
}
}
});
thread.start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(m.as);
}
public void increase() {
as++;//取值,加1,赋值
}
}
- 多线程对静态变量进行改变
public class VolatileTest {
public static int as = 0;
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (VolatileTest.class) {
for (int n = 0; n < 1000; n++) {
increase();
}
}
}
});
thread.start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(as);
}
public static void increase() {
as++;//取值,加1,赋值
}
}
总结: 对于静态变量,应该锁Class;对于对象内部的变量,应该锁this/实例对象/方法前加锁