多线程:初识同步代码块和同步函数

来源:互联网 发布:菜刀切到手 知乎 编辑:程序博客网 时间:2024/05/22 10:56

以卖票的问题为例:

// 需求:卖票 四个窗口同时卖100张票。

/* 线程安全问题产生的原因:
 * 1.多个线程操作共享的数据。
 * 2.操作共享数据的线程代码有多条。
 * 
 * 当一个线程在执行操作共享数据的多条代码的过程中,其他线程参与了运算。就会导致 线程出现安全问题。
 * 
 * 解决思路:将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程是不可以参与运算的
 *   必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。
 * 
 * 在java中用同步代码块就可以解决这个问题。
 * 
 * 同步代码块的格式是:
 * synchronized(对象)
 * {
 * 需要被同步的代码;
 * }
 * 
 * 同步的好处:解决了线程的安全问题。
 * 
 * 同步的弊端:相对降低了效率,因为同步外的线程都会判断同步锁。
 * 
 * 同步的前提:同步中必须有多个线程并且使用同一个锁。
 * */
class Ticket implements Runnable//extends Thread
{
private static int num  = 100;
Object obj = new Object();
public void run()
{
sale();
}
public void sale()
{
while(true)
{
synchronized(obj)//当一个线程在执行操作共享数据的多条代码的过程中,其他线程参与了运算。就会导致 线程出现安全问题。
{

if(num>0) 
{
try {

Thread.sleep(10);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println(Thread.currentThread().getName()+"....sale...."+num--);
}
}
}
}
}
public class TicktDemo {
public static void main(String[] args) {
Ticket t = new Ticket();//创建一个线程任务对象。
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
// Ticket t1 = new Ticket();
// Ticket t2 = new Ticket();
// Ticket t3 = new Ticket();
// Ticket t4 = new Ticket();
// t1.start();
// t2.start();
// t3.start();
// t4.start();
}

}


同步代码块和同步函数的比较

/* 同步函数使用的锁是this;
 * 
 * 同步函数和同步代码块的区别:
 * 同步函数使用的锁是固定的this
 * 
 * 同步代码块的锁是任意的对象。
 * 
 * 建议使用同步代码块。
 * */


/* 静态的同步函数使用的锁是该函数所属的字节码文件对象,该对象可以用this.getClass()获取,也可以用当前类名.class 表示。
 * */
public class SynFunctionLockDemo {
public static void main(String[] args) {
Ticket1 t = new Ticket1();//创建一个线程任务对象。
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try {

Thread.sleep(10);
} catch (InterruptedException e) {
// TODO: handle exception
}
t.flag = false;
t2.start();


}
}
class Ticket1 implements Runnable//extends Thread
{
private static int num  = 100;
Object obj = new Object();
boolean flag = true;
public void run()
{
sale();
}
public void sale()
{
if(flag)
{

while(true)
{
synchronized(Ticket1.class)//(this.getClass())
{
if(num>0) 
{
try {

Thread.sleep(10);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println(Thread.currentThread().getName()+"....obj...."+num--);
}
}
}
}else
{
while(true)
{

show();
}
}
}
public static synchronized void show()//若同步函数为静态的,则同步函数就只能使用类的class文件对象作为它的锁,这个对象用getClass方法获得。
{
if(num>0) 
{
try {

Thread.sleep(10);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println(Thread.currentThread().getName()+"....function...."+num--);
}
// }

}
}