Synchronized锁的用法 —(java笔记)
一、 先看看不使用synchronized会导致什么问题
直接上代码
public class Thread1 implements Runnable{
static Thread1 instance = new Thread1();
static int i = 0;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int j = 0; j < 100000; j++) {
i++;
}
}
}
-
我们预期的结果应该是 200000
-
但事实上并不是,结果都是小于等于200000的
结果示例
143455
幸亏只是数字,如果是我们手上白花花的银子就糟糕了
为什么会导致这个问题呢?
因为线程每一步修改i的大小实际上要经过三步:
- 先拿到i
- 修改i
- 把i放回内存
假如第一个线程只是修改了i=9+1,还没放回内存,第二个线程也拿到了i=9,两个线程放进内存的i都是10,就导致了i少了1,也就相当于丢了一块钱,好难过~~~
二、所以我们的锁就应运而生了
对象锁我感觉就是对同一个对象进行操作
类锁就是对不同对象进行操作 (可能不太对)
- 对象锁第一种形式(代码块) 直接上代码 —可以根据自己想法修改块的数量和块指向的对象
public class SynchronizedObjectCodeBlock implements Runnable{
static SynchronizedObjectCodeBlock instance = new SynchronizedObjectCodeBlock();
Object lock1 = new Object();
Object lock2 = new Object();
@Override
public void run() {
// TODO Auto-generated method stub
//可以用this自身对象 也可以新创对象 手动指定锁对象
synchronized(lock1) {
System.out.println("我是对象锁的代码块形式。我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行完毕");
}
// synchronized(lock2) {
// System.out.println("我是对象锁的代码块形式。我叫"+Thread.currentThread().getName());
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName()+"运行完毕");
// }
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
//和t1.join()效果是一样的 判断线程是否还在运行
while(t1.isAlive() || t2.isAlive()) {
}
System.out.println("finished");
}
}
运行结果:
我是对象锁的代码块形式。我叫Thread-0
Thread-0运行完毕
我是对象锁的代码块形式。我叫Thread-1
Thread-1运行完毕
finished
- 对象锁第二种形式(方法锁) 直接上代码
public class SynchronizedObjectMethod implements Runnable{
static SynchronizedObjectMethod instance = new SynchronizedObjectMethod();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive() || t2.isAlive()) {
}
System.out.println("finished");
}
@Override
public void run() {
method();
}
//默认锁对象为自身 this
public synchronized void method() {
System.out.println("我是对象锁的方法修饰形式,我叫"+Thread.currentThread().getName());
try{
Thread.sleep(3000);
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行完毕");
}
}
运行结果:
我是对象锁的方法修饰形式,我叫Thread-0
Thread-0运行完毕
我是对象锁的方法修饰形式,我叫Thread-1
Thread-1运行完毕
finished
- 类锁的第一种形式(静态方法上加锁) 直接上代码
public class SynchronizedClassStatic implements Runnable{
static SynchronizedClassStatic instance1 = new SynchronizedClassStatic();
static SynchronizedClassStatic instance2 = new SynchronizedClassStatic();
@Override
public void run() {
method();
}
//静态方法上加锁
public static synchronized void method() {
System.out.println("我是类锁的第一种形式static,我叫"+Thread.currentThread().getName());
try{
Thread.sleep(3000);
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行完毕");
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
t1.join();
System.out.println("finished");
}
}
运行结果:
我是类锁的第一种形式static,我叫Thread-0
Thread-0运行完毕
我是类锁的第一种形式static,我叫Thread-1
Thread-1运行完毕
finished
- 类锁的第二钟形式(synchronized(*.class)) 直接上代码
public class SynchronizedClassClass implements Runnable {
static SynchronizedClassClass instance1 = new SynchronizedClassClass();
static SynchronizedClassClass instance2 = new SynchronizedClassClass();
@Override
public void run() {
method();
}
private void method() {
synchronized (SynchronizedClassClass.class) {
System.out.println("我是类锁的第二种形式,synchronized(*.class)。我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行完毕");
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
while(t1.isAlive() || t2.isAlive()) {
}
System.out.println("finished");
}
}
运行结果:
我是类锁的第二种形式,synchronized(*.class)。我叫Thread-0
Thread-0运行完毕
我是类锁的第二种形式,synchronized(*.class)。我叫Thread-1
Thread-1运行完毕
finished