线程同步
为什么需要“线程同步”
线程间共享代码和数据可以节省系统开销,提高程序运行效率,
但同时也导致了数据的“访问冲突”问题,
如何实现线程间的有机交互、并确保共享资源在某些关键时段只能被一个线程访问,即所谓的“线程同步”(Synchronization)就变得至关重要。
synchronized关键字的使用方式有两种:
用在对象前面限制一段代码的执行(同步代码块)
public void push(char c){
…
sychronized(this){
data[index]=c;
index++
}
}
用在方法声明中,表示整个方法为同步方法
同步代码块可以使用任意对象作为锁,同步方法使用的锁只有一个--this。static同步方法使用的锁是该方法所属类的对象。类型.class
同步好处:决了线程安全问题
同步弊端
降低了运行效率(判断锁是较为消耗资源的)
同步嵌套,容易出现死锁
/*
同步的两种表现形式:
1,同步代码块:需要一个锁。
2,同步函数:问:同步函数用的是哪个锁呢?
需求:将售票程序通过同步函数的形式解决一下线程安全问题。
*/
class SaleTicket implements Runnable
{
privateint tick = 100;
public void run()
{
while(true)
{
show();
}
}
publicsynchronized void show()
{
if(tick>0)
{
try{Thread.sleep(100);}catch(Exceptione){}
System.out.println(Thread.currentThread().getName()+".....sale......"+tick--);
}
}
}
class ThreadDemo6
{
publicstatic void main(String[] args)
{
SaleTickett = new SaleTicket();
Threadt1 = new Thread(t);
Threadt2 = new Thread(t);
Threadt3 = new Thread(t);
Threadt4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
下面线程同步的售票应用:
package cn.csdn.hr.thread;
publicclass Sale {
/**
* 售票的应用
* @param args
*/
publicstaticvoid main(String[] args){
Ticket t = new Ticket();
Thread t1 =new Thread(t);
Thread t2 =new Thread(t);
t1.start();
t2.start();
}
}
class Ticketimplements Runnable{
privateints= 100;
Object obj = new Object();
@Override
publicvoid run(){
while(true){
show();
}
/*if(s>0){
try{
Thread.sleep(100);
}catch (InterruptedException e) {
//TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"....."+s--);
}*/
}
publicsynchronizedvoid show(){
if(s>0){
try {
Thread.sleep(100);
} catch(InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"....."+s--);
}
}
}
/**
*同步的两种方法:
*
* 1.
*
* synchronized (对象){
* 同步的代码块
* }
*
* 2.采用函数的方法:使用的锁是 this
* public synchronized void show(){//同步函数
* 同步的代码块
* }
*
*
*
*单例模式:
*懒汉式:结合线程的应用
*同步对象
* class Single{
* private static Single s = null;
* private Single(){}
* public static Single getInstance(){
* if(s==null){
* synchronized(Single.class){
* if(s==null){
* s = new Single();
* }
* }
* return s;
*
* }
*
*
*同步函数
* class Single{
* private static Single s = null;
* private Single(){}
* public static synchronized SinglegetInstance(){
* if(s==null){
* s = new Single();
* return s;
* }
*
* }
*饿汉式:
* class Single{
* private static Single s = new Single();
* private Single(){}
* public static Single getInstance(){
* return s;
* }
* }
*/
第二个事例:
package cn.csdn.hr.thread;
class Tickets{
publicinttickets;
public Tickets() {
tickets = 10;
}
publicsynchronizedvoid action(String name){
System.out.println(name+"卖了"+tickets+"张");
tickets--;
}
}
class TicketsThreadextends Thread{
Tickets t;
String name;
publicTicketsThread(Tickets t, String name) {
this.t = t;
this.name = name;
start();
}
public void run(){
try{
for(int i = 0;i<5;i++){
t.action(name);
Thread.sleep(20);
}
}catch(Exception e){}
}
}
publicclass TestThread {
/**
* 售票
* @param args
*/
publicstaticvoid main(String[] args){
Tickets t =new Tickets();
TicketsThreadd1 = new TicketsThread(t,"我");
TicketsThreadd2 = new TicketsThread(t,"你");
}
}