当多个线程访问同一个资源时,导致了数据有问题。CPU在多个线程之间高速切换导致。
示例
public class MyTicket implements Runnable{
//定义100张票
int ticket = 100;
@Override
public void run() {
while(true){
if (ticket>0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
ticket--;
}
}
}
}
public class Test01 {
public static void main(String[] args) {
MyTicket myTicket = new MyTicket();
Thread t1 = new Thread(myTicket, "赵四");
Thread t2 = new Thread(myTicket, "刘能");
Thread t3 = new Thread(myTicket, "广坤");
t1.start();
t2.start();
t3.start();
}
}
方式一:同步代码块
基本流程:
- 格式:
synchronized(任意对象){
线程可能出现不安全的代码
}
- 任意对象:就是我们的锁对象
- 执行:
- 一个线程拿到锁之后,会进入到同步代码块中执行,在此期间,其他线程拿不到锁,就进不去同步代码块,需要在同步代码块外面等待排队
- 需要等着执行的线程执行完毕,出了同步代码块,相当于释放锁了,等待的线程才能抢到锁,才能进入到同步代码块中执行
public class MyTicket implements Runnable{
//定义100张票
int ticket = 100;
//任意new一个对象
Object obj = new Object();
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (obj){
if (ticket>0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
ticket--;
}
}
}
}
}
public class Test01 {
public static void main(String[] args) {
MyTicket myTicket = new MyTicket();
Thread t1 = new Thread(myTicket, "赵四");
Thread t2 = new Thread(myTicket, "刘能");
Thread t3 = new Thread(myTicket, "广坤");
t1.start();
t2.start();
t3.start();
}
}
方法二:同步方法
普通同步方法
基本流程:
- 格式:
修饰符 synchronized 返回值类型 方法名(参数){
方法体
return 结果
}
- 默认锁:this
public class MyTicket implements Runnable{
//定义100张票
int ticket = 100;
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//method01();
method02();
}
}
/*
public synchronized void method01(){
if (ticket>0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
ticket--;
}
}
*/
public void method02(){ //
synchronized(this){
System.out.println(this+"..........");
if (ticket>0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
ticket--;
}
}
}
}
public class Test01 {
public static void main(String[] args) {
MyTicket myTicket = new MyTicket();
System.out.println(myTicket);
Thread t1 = new Thread(myTicket, "赵四");
Thread t2 = new Thread(myTicket, "刘能");
Thread t3 = new Thread(myTicket, "广坤");
t1.start();
t2.start();
t3.start();
}
}
静态同步方法
基本流程:
- 格式:
修饰符 static synchronized 返回值类型 方法名(参数){
方法体
return 结果
}
- 默认锁:class对象
public class MyTicket implements Runnable{
//定义100张票
static int ticket = 100;
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//method01();
method02();
}
}
/*public static synchronized void method01(){
if (ticket>0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
ticket--;
}
}*/
public static void method02(){
synchronized(MyTicket.class){
if (ticket>0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
ticket--;
}
}
}
}
public class Test01 {
public static void main(String[] args) {
MyTicket myTicket = new MyTicket();
Thread t1 = new Thread(myTicket, "赵四");
Thread t2 = new Thread(myTicket, "刘能");
Thread t3 = new Thread(myTicket, "广坤");
t1.start();
t2.start();
t3.start();
}
}