4.线程同步问题
同步问题:每一个线程对象轮番抢占共享资源带来的问题(针对多线程问题)
package www.wl.java;
class MyThread implements Runnable {
private int ticket = 10 ; // 一共十张票
@Override
public void run() {
while(this.ticket>0) { // 还有票
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 模拟网络延迟
System.out.println(Thread.currentThread().getName()+",还有" +this.ticket -- +" 张票");
}
}
}
public class Test {
public static void main(String[] args) {
MyThread mt = new MyThread() ;
new Thread(mt,"黄牛A").start();
new Thread(mt,"黄牛B").start();
new Thread(mt,"黄牛C").start();
}
}
结果:
黄牛C,还有10 张票
黄牛B,还有8 张票
黄牛A,还有9 张票
黄牛C,还有7 张票
黄牛B,还有5 张票
黄牛A,还有6 张票
黄牛C,还有4 张票
黄牛B,还有2 张票
黄牛A,还有3 张票
黄牛B,还有1 张票
黄牛A,还有0 张票
黄牛C,还有-1 张票
Process finished with exit code 0
这个时候我们发现,票数竟然出现负数,这种问题我们称之为不同步操作。
不同步的唯一好处是处理速度快(多个线程并发执行)
4.1同步处理
4.1.1使用synchronized(对象锁)关键字来处理同步问题
synchronized处理同步有两种模式:同步代码块,同步方法
同步代码块:要使用同步代码块必须要设置一个锁定的对象,一般可以锁定当前对象this,表示同一时刻只有一个线程能够进入同步代码块,但是多个线程可以同时进入方法
代码如下:package www.wl.java;
class MyThread implements Runnable { // 线程主体
private int ticket=10;
@Override
public void run() {
for(int i=0;i<10;i++){
//为程序上锁
synchronized (this){
if(this.ticket>0) {
try {
Thread.sleep (200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace ();
} // 模拟网络延迟
System.out.println (Thread.currentThread ().getName () + ",还有" + this.
ticket-- + " 张票");
}
}
}
}
}
public class test {
public static void main(String[] args) {
MyThread mt = new MyThread() ;
new Thread(mt,"黄牛A").start();
new Thread(mt,"黄牛B").start();
new Thread(mt,"黄牛C").start();
}
}
结果:
黄牛A,还有10 张票
黄牛A,还有9 张票
黄牛C,还有8 张票
黄牛C,还有7 张票
黄牛B,还有6 张票
黄牛C,还有5 张票
黄牛A,还有4 张票
黄牛C,还有3 张票
黄牛B,还有2 张票
黄牛C,还有1 张票
同步方法:在方法中使用synchronized关键字,表示此方法只有一个线程能够进入。隐式锁对象,this
代码如下:
package www.bit.java;
class MyThread implements Runnable { // 线程主体
private int ticket=100;
@Override
public void run() {
for(int i=0;i<100;i++) {
sale ();
} }
//表示此方法只有一个线程能够进入
public synchronized void sale(){
if(ticket>0) {
System.out.println (Thread.currentThread ().getName () + ",还有" + this.ticket-- + " 张票");
}
}
}
public class 多线程 {
public static void main(String[] args) {
MyThread mt = new MyThread() ;
new Thread(mt,"黄牛A").start();
new Thread(mt,"黄牛B").start();
new Thread(mt,"黄牛C").start();
}
}
关于synchronized的对象锁概念,里面锁个对象
Synchronized(this)以及普通的synchronized方法,只能防止多个线程执行同一对象的同步段,synchronized锁的是括号中的对象而非代码
全局锁:锁代码段
1.synchronized与static一起使用,此时锁的是当前使用的类而非对象
2.在代码块中锁当前Class对象
Synchronized(Sync.class)即:(类名称.class){}