java线程同步等基础知识

一、线程同步

线程安全API与非线程安全API

StringBuffer是同步的 synchronized append()

StringBuilder不是同步的 append();

Vector Hashtable是同步的

ArrayListHashMap不是同步的

二、synchronized关键字

多个线程并发读写同一个临界资源是会发生“线程并发”安全等问题

锁机制:

java提供了一种内置的锁机制用来支持原子性:

同步代码快,同步代码快包含两部分:

一个作为锁的对象的引用

一个作为有这个锁保护的代码

synchronized(同步监视器-锁对象引用){

}

--  若方法 所有代码都需要同步与也可以方法直接加锁

-- 每个java对象都可以用做一个实现同步的锁。线程进入同步代码块之前自动获得锁,并且退出同步代码块时自动释放放锁,而且不论是通过正常途径退出,还是通过抛出异常退出都一样,获得内置锁的唯一正常途径就是进入这个锁保护的同步的代码块和方法/

 

 

常见的临界资源(所谓的临界资源可以参考:计算机操作系统临界资源):

--多线程共享实例变量

--多线程共享静态公共变量

解决线程的安全的解决方案:

--异步操作:多线程并发,相当于各干各的

--同步操作: 有先后顺序的操作,相当于你干完我干

测试代码:

/**

 * 多线程并发安全问题

 * 当多个线程同时操作同一资源是,由于线程切换时机不明确,导致出现逻辑混乱

 * 严重时可能导致系统崩溃

 *

 * @author soft01

 *

 */

public class SyncDemo1 {
public static void main(String[] args) {
/*
 * 当一个方法中的局部内部类引用该方法的其他局部变量时,这个变量必须被申明为final的
 * Thread t1=new Thread()作为内部类
 *
 */
final Table table=new Table();
Thread t1=new Thread(){
public void run(){
while(true){
int bean=table.getBean();
Thread.yield();
System.out.println(getName()+":"+bean);
}
}
};
t1.start();
Thread t2=new Thread(){
public void run(){
while(true){
int bean=table.getBean();
Thread.yield();
System.out.println(getName()+":"+bean);
}
}
};
t2.start();
}
}
class Table{
private int beans=20;
/*
 * 当一个方法被SYSNCHRONIZED修饰后,
 * 该方法成为“同步方法”多个线程不能同时进入到内部
 */
public synchronized int getBean(){
if(beans==0){
throw new RuntimeException("没有豆子");
}
Thread.yield();//模拟进程切换
return beans--;
}
}

测试代码:

/**

 *  有效的缩小同步范围可以保证在安全

 *  的前提下提高并发的效率

 *  在这个程序中我们提前假设 :换衣服时---> 可能导致 取错别人的衣服,所以在需要排队.

 * @author soft01

 *

 */

public class SyncDemo2 {
public static void main(String[] args) {
final Shop shop=new Shop();
Thread t0=new Thread(){
public void run() {
shop.bye();
}
};
Thread t1=new Thread(){
public void run() {
shop.bye();
}
};
t0.start();
t1.start();
}
}
class Shop{
public void bye(){
try{
Thread t=Thread.currentThread();
System.out.println(t+"正在挑衣服");
Thread.sleep(5000);
/*
 * 同步块可以缩小同步范围
 * 但是必须保证和"同步监视器":即 上锁对象
 * 是同一个才可以
 * 通常,在一个方法中使用this来表示
 */
synchronized (this) {//这里的this不能换成:new object(),必须要保证看到的是同一对象
System.out.println(t+"正在试衣服");
Thread.sleep(5000);
}
System.out.println("结帐离开");
}catch(Exception e){
e.printStackTrace();
}
}
}

测试代码:

/**

 * synchronized也称为“互斥锁”;

 * synchronized修饰的两端代码,但是“锁对象”相同时,即是互斥锁

 * @author soft01

 *

 */

public class Synchronized {
public static void main(String[] args) {
final Boo boo=new Boo();
Thread t1=new Thread(){
public void run(){
boo.methodA();
}
};
Thread t2=new Thread(){
public void run(){
boo.methodB();
}
};
t1.start();
t2.start();
}
}
class Boo{
public synchronized void methodA(){
Thread t=Thread.currentThread();
System.out.println(t+"正在调用方法");
try{
Thread.sleep(5000);
}catch (InterruptedException e) {
e.printStackTrace();
// TODO: handle exception
}
System.out.println(t+"调用完毕");
}
public synchronized void methodB(){
Thread t=Thread.currentThread();
System.out.println(t+"正在调用方法");
try{
Thread.sleep(5000);
}catch (InterruptedException e) {
e.printStackTrace();
// TODO: handle exception
}
System.out.println(t+"调用完毕");
}
}

测试结果:

Thread[Thread-0,5,main]正在调用方法

Thread[Thread-0,5,main]调用完毕

Thread[Thread-1,5,main]正在调用方法

Thread[Thread-1,5,main]调用完毕

 

三 集合线程安全

/**

 * ArrayList,Linkedlist,HashSet 都不是线程安全的,

 *Map常用的实现类HshMap也不是线程安全的

 * 而线程安全的集合ListVector,线程安全的Map的实现类是HashTable

 * 可以使用Collections提供的静态方法可以将当前的集合或Map转换为线程安全

 * Collection 是接口

 * Collections是工具类

 *

 * @author soft01

 *

 */

测试代码:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class SyncApiDemo {
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
/*
 * 将给定的List集合转换为线程安全的集合
 * 返回的集合中仍然包含所有元素
 */
list=Collections.synchronizedList(list);
System.out.println(list);
//HashSet不是线程安全的
Set<String> set=new HashSet<String>(list);
//转换为线程安全集合
set=Collections.synchronizedSet(set);
Map<String,Integer> map=new HashMap<String, Integer>();
map.put("语文",1);
map.put("数学",3);
map.put("英语",2);
map=Collections.synchronizedMap(map);
System.out.println(map);
}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值