线程同步
package com.csdn;
class Tickets{
public int tickets;
public Tickets(){
tickets = 10;
}
}
public class SaleTicket {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Tickets t = new Tickets();
Ticket st1 = new Ticket(t,"小王");
Ticket st2 = new Ticket(t,"小张");
}
}
class Ticket extends Thread {
Tickets t;
String name;
public Ticket(Tickets t,String name){
this.t = t;
this.name = name;
start();
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0; i<5; i++){
System.out.println(name+"抢到了第"+t.tickets+"票号");
t.tickets--;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package com.csdn;
public class SaleTickets {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SaleTicke st = new SaleTicke();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
}
}
class SaleTicke implements Runnable{
private int tickets = 20;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
if(tickets>0){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"......"+tickets--);
}
}
}
}
为什么需要“线程同步” ??
线程间共享代码和数据可以节省系统开销,提高程序运行效率,但同时也导致了数据的“访问冲突”问题
如何实现线程间的有机交互、并确保共享资源在某些关键时段只能被一个线程访问,即所谓的“线程同步”(Synchronization)就变得至关重要。
临界资源: 多个线程间共享的数据称为临界资源(Critical Resource),
由于是线程调度器负责线程的调度,程序员无法精确控制多线程的交替顺序。因此,多线程对临界资源的访问有时会导致数据的不一致行。
互斥锁
每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
Java对象默认是可以被多个线程共用的,只是在需要时才启动“互斥锁”机制,成为专用对象。
关键字synchronized用来与对象的互斥锁联系
当某个对象用synchronized修饰时,表明该对象已启动“互斥锁”机制,在任一时刻只能由一个线程访问,即使该线程出现堵塞,该对象的被锁定状态也不会解除,其他线程任不能访问该对象。
synchronized关键字的使用方式有两种:
1.同步代码块
synchronized(对象){
需要同步的代码
}
2.同步函数: 使用的锁是this
public synchronized void show(){
}
-
用在对象前面限制一段代码的执行(同步代码块)
package com.csdn;
class Tickets1{
public int tickets;
public Tickets1(){
tickets = 10;
}
}
public class TestMulThread2{
/**
* @param args
*/
public static void main(String[] args) {
Tickets1 t = new Tickets1();
Ticket1 st1 = new Ticket1(t,"小王");
Ticket1 st2 = new Ticket1(t,"小张");
}
}
class Ticket1 extends Thread {
static String st1 ="aaa";
Tickets1 t;
String name;
public Ticket1(Tickets1 t,String name){
this.t = t;
this.name = name;
start();
}
public synchronized void show(){//同步代码块
System.out.println(name+"抢到了第"+t.tickets+"票号");
t.tickets--;
}
@Override
public void run() {
for(int i=0; i<5; i++){
synchronized(st1){
System.out.println(name+"抢到了第"+t.tickets+"票号");
t.tickets--;
}
//show();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package com.csdn;
public class SaleTicketsSy {
public static void main(String[] args) {
// TODO Auto-generated method stub
SaleTicketsy st = new SaleTicketsy();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
}
}
class SaleTicketsy implements Runnable{
private int tickets = 100;
@Override
public void run() {
// TODO Auto-generated method stub
Object obj = new Object();
while(true){
synchronized(obj){//同步代码块
if(tickets>0){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"......"+tickets--);
}
}
}
}
}
-
用在方法声明中,表示整个方法为同步方法
package com.csdn;
public class TestMulThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Tickets2 t = new Tickets2();
TicketsThread d1 = new TicketsThread(t,"Jam");
TicketsThread d2 = new TicketsThread(t,"Jack");
}
}
class Tickets2{
public int tickets;
public Tickets2(){
tickets = 10;
}
public synchronized void action(String name){//锁方法
System.out.println(name+"抢到了第"+tickets+"票号");
tickets--;
}
}
class TicketsThread extends Thread{
Tickets2 t;
String name;
public TicketsThread(Tickets2 t, String name){
this.t = t;
this.name = name;
start();
}
public void run(){
for(int i=0;i<5;i++){
t.action(name);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package com.csdn;
public class SaleTicketsSy2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
SaleTicketsy2 st = new SaleTicketsy2();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
}
}
class SaleTicketsy2 implements Runnable{
private int tickets = 100;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
show();
}
}
public synchronized void show(){//锁方法
if(tickets>0){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"......"+tickets--);
}
}
}
同步好处:决了线程安全问题
同步弊端:降低了运行效率(判断锁是较为消耗资源的)
死锁:同步嵌套,容易出现死锁
死锁 两个线程A、B用到同一个对象s(s为共享资源),且线程A在执行中要用到B运行后所创造的条件。在这种前提下A先开始运行,进入同步块后,对象s被锁定,接着线程A因等待B运行结束而进入阻塞状态,于是B开始运行,但因无法访问对象s,线程B也进入阻塞状态,等待s被线程A解锁。最终的结果:两个线程互相等待,都无法运行。
package com.csdn;
public class DeadLock {
/**
* @param args
*/
public static void main(String[] args) {
Demo6 d1=new Demo6(true);
Demo6 d2=new Demo6(false);
Thread t1=new Thread(d1);
Thread t2=new Thread(d2);
t1.start();
t2.start();
}
}
class MyLock{
static MyLock lock1=new MyLock();
static MyLock lock2=new MyLock();
}
class Demo6 implements Runnable{
//String str1=new String("aaa");
//String str2=new String("bbb");
private boolean flag;
public Demo6(boolean flag){
this.flag=flag;
}
@Override
public void run() {
if(flag){
synchronized(MyLock.lock1){
System.out.println(Thread.currentThread().getName()+"...if...str1");
synchronized(MyLock.lock2){
System.out.println(Thread.currentThread().getName()+"...if...str2");
}
}
}else{
synchronized(MyLock.lock2){
System.out.println(Thread.currentThread().getName()+"...else...str2");
synchronized(MyLock.lock1){
System.out.println(Thread.currentThread().getName()+"...else...str1");
}
}
}
}
}
分析:这是线程死锁的典型表现,两个以上线程并发运行,他们均因其他线程锁定了自己运行所需资源而陷入阻塞状态,同时自己也锁定了其他线程所需资源。
单例类
懒汉式
class Single{
private static Single s=null;
private Single(){}
public static Single getInstance(){
if(s==null)
synchronized(Singel。class){
if(s==null)
s=new Single();
}
return s;
}
class Single{
private static Single s=null;
private Single(){}
public static synchronized Single getInstance(){
if(s==null)
s=new Single();
return s;}
Single.getInstance();
饿汉式
class Single{
private static Single s=new Single();
private Single(){}
public static Single getInstance(){
return s;
}
}
分享到:
相关推荐
Java多线程实例,是学习java多线程的好方法
详细介绍的JAVA的多线程程序设计
实现多线程TCP传输,同时分成发送方和接受方
黑马程序员_张孝祥_Java多线程与并发库,视频+代码+资料
c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程c_多线程...
多线程下载,随便做的,有一定的局限性,仅供参考
Java中的多线程结构请大家观看不足的地方请指教,大家可以一语既出的观看和指导。
一个简单记录java多线程下变量共享问题,分析多线程内部运行
2.讲解了在多线程中对并发访问的控制, 主要就是synchronized的使用, 由于此关键字在使用上非常灵活, 所以书中用了很多案例来介绍此关键字的使用, 为读者学习同步相关内容打好坚实的基础。3.介绍线程并不是孤独的...
java的打字程序,包含了多线程编写的练习和Applet的编程练习。
实现了多线程电梯的调度算法(3部电梯统一进行调度)
smoker_java多线程_源码.zip
张孝祥Java多线程与并发库高级应用学习笔记,很经典的学习多线程和并发的资料。张孝祥Java多线程讲义笔记由张孝祥亲自整理,很实用的。
多线程TCP连接,用java实现 多线程TCP连接,用java实现
JAVA解惑_Java多线程_JS_HTML5.zip
_Java多线程编程详解.doc
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
多线程与并发处理是程序设计好坏优劣的重要课题,本书通过浅显易懂的文字和示例来介绍与java线程相关的设计模式理念
Java_servlet多线程 Java_servlet多线程
基于java多线程的通信,类似QQ,包括客户端和服务端。