多个线程同时处理同一资源的线程不安全实例,线程1和2同时操作ticket
package com.chocus.demo1;
public class ThreadDemo6 {
public static void main(String[] args) {
MyRunnable6 mr = new MyRunnable6();
Thread t = new Thread(mr);
Thread t2 = new Thread(mr);
t.start();
t2.start();
}
}
class MyRunnable6 implements Runnable {
private int ticket = 10;
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (ticket > 0) {
ticket--;
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("剩余票数" + ticket + "张");
}
}
}
}
结果
剩余票数8张
剩余票数7张
剩余票数6张
剩余票数6张
剩余票数4张
剩余票数4张
剩余票数2张
剩余票数1张
剩余票数0张
剩余票数0张
当线程sleep时,会交出执行权,但不会释放锁。
使用同步代码块:
package com.chocus.demo1;
public class ThreadDemo6 {
public static void main(String[] args) {
MyRunnable6 mr = new MyRunnable6();
Thread t = new Thread(mr);
Thread t2 = new Thread(mr);
t.start();
t2.start();
}
}
class MyRunnable6 implements Runnable {
private int ticket = 10;
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (ticket > 0) {
synchronized (this) {
ticket--;
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("剩余票数" + ticket + "张");
}
}
}
}
}
结果
剩余票数9张
剩余票数8张
剩余票数7张
剩余票数6张
剩余票数5张
剩余票数4张
剩余票数3张
剩余票数2张
剩余票数1张
剩余票数0张
同步方法:同步的对象是当前对象(this)
package com.chocus.demo1;
public class ThreadDemo6 {
public static void main(String[] args) {
MyRunnable6 mr = new MyRunnable6();
Thread t = new Thread(mr);
Thread t2 = new Thread(mr);
t.start();
t2.start();
}
}
class MyRunnable6 implements Runnable {
private int ticket = 10;
@Override
public void run() {
for (int i = 0; i < 20; i++) {
method();
}
}
private synchronized void method() {
if (ticket > 0) {
ticket--;
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("剩余票数" + ticket + "张");
}
}
}
结果
剩余票数9张
剩余票数8张
剩余票数7张
剩余票数6张
剩余票数5张
剩余票数4张
剩余票数3张
剩余票数2张
剩余票数1张
剩余票数0张
Lock锁:比同步代码块和同步方法更灵活。同步代码块需要执行完毕后释放锁,而同步方法要方法执行完毕后释放锁。
package com.chocus.demo1;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo6 {
public static void main(String[] args) {
MyRunnable6 mr = new MyRunnable6();
Thread t = new Thread(mr);
Thread t2 = new Thread(mr);
t.start();
t2.start();
}
}
class MyRunnable6 implements Runnable {
private int ticket = 10;
ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
for (int i = 0; i < 20; i++) {
method();
}
}
private void method() {
lock.lock();
try {
if (ticket > 0) {
ticket--;
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("剩余票数" + ticket + "张");
}
} finally {
lock.unlock();
}
}
}
结果
剩余票数9张
剩余票数8张
剩余票数7张
剩余票数6张
剩余票数5张
剩余票数4张
剩余票数3张
剩余票数2张
剩余票数1张
剩余票数0张