如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明为同步的。
1.利用 实现Runnable接口 的方式来创建三个线程来卖票 并利用同步方法来解决线程不安全问题
package thread;
//利用 实现Runnable接口 的方式来创建三个线程来卖票
//利用同步方法来解决线程不安全问题
class window4 implements Runnable{
private int ticket = 100;
@Override
public void run() {
while(true){
show();
if(ticket==0){
break;
}
}
}
private synchronized void show(){
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "票号为:" + ticket);
ticket--;
} else {
System.out.println("没票啦");
}
}
}
public class synchronizedTest {
public static void main(String[] args){
window4 w = new window4();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.start();
t2.start();
t3.start();
}
}
-
注意:重新定义了一个synchronized(同步)方法用来装三个线程操作共享数据的代码,但是while不能放进来,否则是一个线程把所有票卖完了。
-
同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。这里定义的synchronized(同步)方法是非静态的,默认同步监视器是this,也就是当前对象。
-
静态的同步方法,同步监视器是:当前类本身
2. 利用 继承Thread类 的方式来创建三个线程来卖票 并利用同步方法来解决线程不安全问题
package thread;
class mythread03 extends Thread{
private static int ticket = 100;
@Override
public void run() {
while(ticket>=0){
show();
}
}
private static synchronized void show(){
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "票号为:" + ticket);
ticket--;
} else {
System.out.println("没票啦");
}
}
}
public class synchrinizedTest02 {
public static void main(String[] args){
mythread03 t1 = new mythread03();
mythread03 t2 = new mythread03();
mythread03 t3 = new mythread03();
t1.start();
t2.start();
t3.start();
}
}
-
注意这里的synchronized的show()方法必须声明成static。因为静态的同步方法,同步监视器是:当前类本身。如果不声明为static,非静态同步方法的锁为this,这时三个线程的锁就不是共用的了