用于解决多线程安全问题的方式:
1. 同步代码块 (隐式锁)
2. 同步方法(隐式锁)
3. 同步锁 Lock( jdk 1.5 后)
注意:是一个显示锁,需要通过 lock() 方法上锁,必须通过 unlock() 方法进行释放锁
下面举一个售票例子:
1)同步代码块
package com.lxj.juc;
public class TestSync {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket).start();
new Thread(ticket).start();
new Thread(ticket).start();
}
}
class Ticket implements Runnable{
private int ticket = 100;
@Override
public void run() {
while(true) {
synchronized(this) { //this代表对当前对象上锁
if(ticket > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" : 购票成功,余票为:" + --ticket );
}else {
break;
}
}
}
}
}运行结果: Thread-0 : 购票成功,余票为:99 Thread-0 : 购票成功,余票为:98 Thread-2 : 购票成功,余票为:97 ..... Thread-2 : 购票成功,余票为:7 Thread-0 : 购票成功,余票为:6 Thread-0 : 购票成功,余票为:5 Thread-1 : 购票成功,余票为:4 Thread-1 : 购票成功,余票为:3 Thread-0 : 购票成功,余票为:2 Thread-0 : 购票成功,余票为:1 Thread-2 : 购票成功,余票为:0
2)同步方法
package com.lxj.juc;
public class TestSync {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket).start();
new Thread(ticket).start();
new Thread(ticket).start();
}
}
class Ticket implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
if (ticket > 0) {
int i = purchase();
if(i == 0) {
break;
}
}else {
break;
}
}
}
private synchronized int purchase() {
if (ticket > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : 购票成功,余票为:" + --ticket);
}else {
return 0;
}
return 1;
}
}运行结果: Thread-0 : 购票成功,余票为:99 Thread-0 : 购票成功,余票为:98 Thread-0 : 购票成功,余票为:97 Thread-2 : 购票成功,余票为:96 Thread-1 : 购票成功,余票为:95 .... Thread-1 : 购票成功,余票为:8 Thread-2 : 购票成功,余票为:7 Thread-2 : 购票成功,余票为:6 Thread-0 : 购票成功,余票为:5 Thread-0 : 购票成功,余票为:4 Thread-0 : 购票成功,余票为:3 Thread-2 : 购票成功,余票为:2 Thread-1 : 购票成功,余票为:1 Thread-2 : 购票成功,余票为:0
3)同步锁lock
package com.lxj.juc;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestSync {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket).start();
new Thread(ticket).start();
new Thread(ticket).start();
}
}
class Ticket implements Runnable {
private int ticket = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock(); //上锁
try {
if (ticket > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : 购票成功,余票为:" + --ticket);
}else {
break;
}
} finally {
lock.unlock(); //解锁
}
}
}
}运行结果: Thread-0 : 购票成功,余票为:99 Thread-1 : 购票成功,余票为:98 Thread-1 : 购票成功,余票为:97 Thread-1 : 购票成功,余票为:96 Thread-1 : 购票成功,余票为:95 Thread-2 : 购票成功,余票为:94 ...... Thread-0 : 购票成功,余票为:6 Thread-0 : 购票成功,余票为:5 Thread-1 : 购票成功,余票为:4 Thread-2 : 购票成功,余票为:3 Thread-2 : 购票成功,余票为:2 Thread-2 : 购票成功,余票为:1 Thread-2 : 购票成功,余票为:0