第一课时
目录
前言
观看马士兵JUC学习笔记。
静态方法 不需要对象进行调用(早于对象出现),所以这里synchronized()无法使用this(对象);
手写一个死锁
import java.util.concurrent.TimeUnit;
public class Test {
private static Object o1 = new Object();
private static Object o2 = new Object();
public static void print1(){
synchronized(o1){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("print1******o1");
synchronized (o2){
System.out.println("print1******o2锁");
}
}
}
public static void print2(){
synchronized (o2){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("print2******o2");
synchronized (o1){
System.out.println("print2******o1");
}
}
}
public static void main(String[] args) {
new Thread(() -> {
Test.print1();
},"A").start();
new Thread(() -> Test.print2(),"B").start();
}
}
synchronized在遇到异常的时候就会释放锁
如果不希望释放锁,就要加上try-catch
import java.util.concurrent.TimeUnit;
public class Test1 {
private int count = 5;
synchronized void method(){
System.out.println(Thread.currentThread().getName() + "**********************start");
while (true){
count++;
System.out.println(Thread.currentThread().getName() + "**************count=" + count);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (count % 5 == 0){
int i = 10 / 0;
}
}
}
public static void main(String[] args) {
Test1 test1 = new Test1();
new Thread(() -> test1.method(),"A").start();
new Thread(() -> test1.method(),"B").start();
}
}
volatile和synchronized的区别
volatile只保证可见性,不保证原子性;
synchronized既保证可见性,又保证原子性;
使用原子类
AtomXXX类
AtomXXX类本身方法都是原子性的,但不能保证多个方法连续调用是原子性的(在调用的过程中可能会又其他的方法进来);
AtomicInteger count = new AtomicInteger(0)
count.incrementAndGet() // count++:不具备原子性
面试题:
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
public class Test4 {
private ArrayList list = new ArrayList();
public void add(Object o){
list.add(o);
}
public int size(){
return list.size();
}
public static void main(String[] args) throws InterruptedException {
Test4 test4 = new Test4();
Object lock = new Object();
new Thread(() -> {
synchronized (lock){
System.out.println(Thread.currentThread().getName() + "***start");
if (test4.size() != 5){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "---end");
lock.notify();
}
},"B").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
synchronized (lock){
for (int i = 1; i <= 10; i++) {
test4.add(new Object());
System.out.println("add" + i);
if (test4.size() == 5){
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"A").start();
}
}
解法二:
public class Test4 {
private ArrayList list = new ArrayList();
public void add(Object o){
list.add(o);
}
public int size(){
return list.size();
}
public static void main(String[] args){
Test4 test4 = new Test4();
Object lock = new Object();
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "***启动");
if (test4.size() != 5){
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---结束了");
}
},"B").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
test4.add(new Object());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("add" + i);
if (test4.size() == 5){
latch.countDown();
}
}
},"A").start();
}
}
总结:
- 掌握volatile和synchronized的区别
- 了解JMM模型