当前位置: 首页 > news >正文

wordpress 调用数据库怎么优化标题和关键词排名

wordpress 调用数据库,怎么优化标题和关键词排名,福鼎市建设局网站,做网站网站盈利会怎么样并发编程 我们主流的并发编程思路一般有#xff1a;多进程、多线程 但这两种方式都需要操作系统介入#xff0c;进入内核态#xff0c;是十分大的时间开销 由此而来#xff0c;一个解决该需求的技术出现了#xff1a;用户级线程#xff0c;也叫做 绿程、轻量级线程、协…并发编程 我们主流的并发编程思路一般有多进程、多线程 但这两种方式都需要操作系统介入进入内核态是十分大的时间开销 由此而来一个解决该需求的技术出现了用户级线程也叫做 绿程、轻量级线程、协程 python - asyncio、java - netty22111111111111115 由于 go 语言是 web2.0 时代发展起来的语言go语言没有多线程和多进程的写法其只有协程的写法 golang - goroutine func Print() {fmt.Println(打印印) }func main() {go Print() }我们可以使用这种方式来进行并发编程但这个程序里要注意我们主程序在确定完异步之后结束会立即让程序退出这就导致我们并发的子线程没来得及执行就退出了。 我们可以增加一个Sleep来让主线程让出资源等待子线程执行完毕再进行操作 func Print() {for {time.Sleep(time.Second)fmt.Println(打印印)}}func main() {go Print()for {time.Sleep(time.Second)fmt.Println(主线程)} }另外的Go 语言协程的一个巨大优势是 可以打开成百上千个协程协助程序效率的提升 要注意一个问题 多进程的切换十分浪费时间且及其浪费系统资源 多线程的切换也很浪费时间但其解决了浪费系统资源的问题 协程既解决了切换浪费时间的问题也解决了浪费系统资源的问题 Go语言仅支持协程 Go语言中协程的调度gmp机制 用户新建的协程Goroutine会被加入到同一调度器中等待运行若调度器满则会将调度器中一半的 G 加入到全局队列中其他 P 若没有 G 则会从其他 P 中偷取一半的 G 若所有的都满则会新建 M 进行处理 P 的数量是固定的 注意 M 和 P 不是永远绑定的当一个 P 现在绑定的 M 进入了阻塞等情况P 会自动去寻找空闲的 M 或创建新的 M 来绑定 子 goroutine 如何通知到主 goroutine 其运行状态也就是我们主协程要知道子协程运行完毕之后再进行进一步操作也就是 wait func main() {// 定义 sync.Group 类型的变量用于控制goroutine的状态var wg sync.WaitGroupfor i : 0; i 100; i {go func(i int) {wg.Add(1) // 每次启动一个协程都要开启一个计数器defer wg.Done() // 每次结束之前都要让计数器 -1fmt.Println(这次打印了: strconv.Itoa(i))}(i)}wg.Wait()fmt.Println(结束..................................) }锁 Go语言中的锁 互斥锁 我们看下面这个程序 var total int var wg sync.WaitGroupfunc add() {defer wg.Done()for i : 0; i 100000; i {total 1} }func sub() {defer wg.Done()for i : 0; i 100000; i {total - 1} }func main() {wg.Add(2)go add()go sub()wg.Wait()fmt.Println(total)/*-10000110000168595...*/ } 我们发现这个程序的结果不可预知这是因为 a 的操作分为三步 取得 a 的值、执行 a 的计算操作、写入 a 的值这三步不是原子性的如果发生了交叉则一个数准备写入时发生协程切换这时后面再做再多的操作也会被这次切换屏蔽掉最终写入这一个数的结果由此可知这种非原子性操作共享数据的模式是不可预知结果的。 那么我们就需要加锁像下面这样 var total int var wg sync.WaitGroup var lock sync.Mutex var lockc lockfunc add() {defer wg.Done()for i : 0; i 100000; i {lock.Lock() // 加锁直至见到自己这把锁的 Unlock() 方法之前令这中间的方法都为原子性的total 1lock.Unlock() // 解锁配合 Lock() 方法使用} }func sub() {defer wg.Done()for i : 0; i 100000; i {lockc.Lock()total - 1lockc.Unlock()} }func main() {wg.Add(2)go add()go sub()wg.Wait()fmt.Println(total)fmt.Printf(%p\n, lock)fmt.Printf(%p\n, (*lockc)) }注意上面这个程序不仅演示了加锁还演示了浅拷贝不影响加锁的情况 另外我们也可以使用 automic 对简单的数值计算进行加锁 var total int32 var wg sync.WaitGroup var lock sync.Mutex var lockc lockfunc add() {defer wg.Done()for i : 0; i 100000; i {atomic.AddInt32(total, 1)} }func sub() {defer wg.Done()for i : 0; i 100000; i {atomic.AddInt32(total, -1)} }func main() {wg.Add(2)go add()go sub()wg.Wait()fmt.Println(total) }读写锁 读写锁就是允许同时读不允许同时写不允许同时读写 func main() {var num intvar rwlock sync.RWMutex // 定义一个读写锁var wg sync.WaitGroup // 定义等待处理器wg.Add(2)go func() {defer wg.Done()rwlock.Lock() // 写锁defer rwlock.Unlock()num 12}()// 同步处理器这里是简便处理time.Sleep(1)go func() {defer wg.Done()rwlock.RLock()defer rwlock.RUnlock()fmt.Println(num)}()wg.Wait()}一个简单的测试 func main() {var rwlock sync.RWMutex // 定义一个读写锁var wg sync.WaitGroup // 定义等待处理器wg.Add(6)go func() {time.Sleep(time.Second)defer fmt.Println(释放写锁可以进行读操作)defer wg.Done()rwlock.Lock() // 写锁defer rwlock.Unlock()fmt.Println(得到写锁停止读操作)time.Sleep(time.Second * 5)}()for i : 0; i 5; i {go func() {defer wg.Done()for {rwlock.RLock()fmt.Println(得到读锁进行读操作)time.Sleep(time.Millisecond * 500)rwlock.RUnlock()}}()}wg.Wait()/**得到读锁进行读操作得到写锁停止读操作释放写锁可以进行读操作得到读锁进行读操作得到读锁进行读操作得到读锁进行读操作*/} 通信 Go 语言中对于并发场景下的通信秉持以下理念 不要通过共享内存来通信要通过通信实现共享内存 其他语言都是用一个共享的变量来实现通信或者消息队列Go语言就希望实现队列的机制 var msg chan string //定义一个用于传递 string 的 channel// 创建一个缓冲区大小为 1 的 channel// 只有 有缓冲区的 channel 才可以暂存数据msg make(chan string, 1)msg - datadata : -msgfmt.Println(data)只有 goroutine 中才可以使用缓冲区大小为 0 的channel func main() {var msg chan string //定义一个用于传递 string 的 channel// 创建一个缓冲区大小为 1 的 channel// 只有 有缓冲区的 channel 才可以暂存数据msg make(chan string, 0)go func(msg chan string) {data : -msgfmt.Println(data)}(msg)msg - datatime.Sleep(time.Second * 3) }这时由于 go 语言 channel 中的 happen-before 机制该机制保证了 就算先 receiver 也会被 goroutine 挂起等待 sender 完成之后再进行 receiver 的具体执行 go 语言中channel 的应用场景十分广泛包括 信息传递、消息过滤信号广播事件订阅与广播任务分发结果汇总并发控制同步异步 Go 语言的消息接收问题 func main() {var msg chan string //定义一个用于传递 string 的 channel// 创建一个缓冲区大小为 1 的 channel// 只有 有缓冲区的 channel 才可以暂存数据msg make(chan string, 0)go func(msg chan string) {// 注意这里每一个接收消息的变量只能接收到一个消息若有多条消息同时发送则无法接收data : -msgfmt.Println(data)math : -msgfmt.Println(math)}(msg)msg - datamsg - mathtime.Sleep(time.Second * 3)}如果我们不知道消息会发送来多少可以使用 for-range 进行监听 func main() {var msg chan string //定义一个用于传递 string 的 channel// 创建一个缓冲区大小为 1 的 channel// 只有 有缓冲区的 channel 才可以暂存数据msg make(chan string, 2)go func(msg chan string) {// 若我们不确定有多少消息会过来我们可以使用 for-range 进行循环验证for data : range msg {fmt.Println(data)}}(msg)msg - datamsg - mathtime.Sleep(time.Second * 3)}close(msg) // 关闭队列监听队列的 goroutine 会立刻退出关闭了的 channel 不能再存储数据但可以进行数据的取出操作 上面我们所接触的 channel 都是双向的 channel 即这个channel 对应的goroutine 既可以从里面读数据也可以向里面写数据这种不符合我们程序一个程序只做它对应的一个功能这一程序设计思路 创建单向 channel var ch1 chan int // 这是一个双向 channelvar ch2 chan- float64 // 这是一个只能写入 float64 类型数据的单向 channelvar ch3 -chan int // 这是一个只能从 存储int型 channel中读取数据的单向channelc : make(chan int, 3) // 创建一个双向 channelvar send chan- int c // 将 c channel 的写入能力赋予给 send使其成为一个单向发送的 channel (生产者)var receive -chan int c // 将c channel 的读取能力赋予给receive使其成为一个单向接收的 channel (消费者)经典例子 /** 经典 使用两个 goroutine 交替打印12AB34CD56EF78GH910IJ1112.....YZ2728 */var number, letter make(chan bool), make(chan bool)func printNum() {// 这里是等待接收消息若消息接收不到则该协程会始终阻塞在这个位置i : 1for {-numberfmt.Printf(%d%d, i, i1)i 2letter - true} }func printLetter() {i : 0str : ABCDEFGHIJKLMNOPQRSTUVWXYZfor {-letterfmt.Print(str[i : i2])number - trueif i 23 {i 2} else {return}}}func main() {go printNum()go printLetter()number - truetime.Sleep(time.Second * 20) } 使用 select 对 goroutine 进行监控 // 使用 struct{} 作为传入的信息由于这个 struct{} 占用内存空间较小这是一种常见的传递方式func g1(ch chan struct{}) {time.Sleep(time.Second * 3)ch - struct{}{} }func g2(ch chan struct{}) {time.Sleep(time.Second * 3)ch - struct{}{} }func main() {g1Channel : make(chan struct{})g2Channel : make(chan struct{})go g1(g1Channel)go g2(g2Channel)// 注意这里只要有一个能取到值则 select 结果则结束select {// 若 g1Channel 中能取到值case -g1Channel:fmt.Println(g1 done)// 若 g1Channel 中能取到值case -g2Channel:fmt.Println(g2 done)} }这里若所有的 goroutine 都就绪了则 select 执行哪个是随机的为的是防止某个 goroutine 一直被优先执行导致的另一个 goroutine 饥饿 超时机制 // 使用 struct{} 作为传入的信息由于这个 struct{} 占用内存空间较小这是一种常见的传递方式func g1(ch chan struct{}) {time.Sleep(time.Second * 3)ch - struct{}{} }func g2(ch chan struct{}) {time.Sleep(time.Second * 3)ch - struct{}{} }func main() {g1Channel : make(chan struct{})g2Channel : make(chan struct{})go g1(g1Channel)go g2(g2Channel)timeChannel : time.NewTimer(5 * time.Second)for {// 注意这里只要有一个能取到值则 select 结果则结束select {// 若 g1Channel 中能取到值case -g1Channel:fmt.Println(g1 done)// 若 g1Channel 中能取到值case -g2Channel:fmt.Println(g2 done)case -timeChannel.C: // timeChannel.C 是获取我们创建的 channel 的方法fmt.Println(time out)return}} }context 使用 WithCancel() 引入手动终止进程的功能 func cpuIInfo(ctx context.Context) {defer wg.Done()for {select {case -ctx.Done(): // 本质还是一个 channelfmt.Println(程序退出执行...........)returndefault:time.Sleep(1 * time.Second)fmt.Println(CPUUUUUUUUUUUUUU)}} }func main() {/**这里有一个问题我们可以将以 context.Background() 为参数的 context 是作为最上层的父 context所有以其他 context 为参数的 context 都是他的子 context只要父 context 调用了 cancel() 则其所有的子 context 都会停止*/ctxParent, cancel : context.WithCancel(context.Background())ctxChild, _ : context.WithCancel(ctxParent)wg.Add(1)go cpuIInfo(ctxChild)time.Sleep(5 * time.Second)cancel() // 这个方法会直接向context channel 中传入一个对象令channel停止wg.Wait() }使用 WthTimeout() 来自动引入超时退出机制 var wg sync.WaitGroupfunc cpuIInfo(ctx context.Context) {defer wg.Done()for {select {case -ctx.Done(): // 本质还是一个 channelfmt.Println(程序退出执行...........)returndefault:time.Sleep(1 * time.Second)fmt.Println(CPUUUUUUUUUUUUUU)}} }func main() {/**这里有一个问题我们可以将以 context.Background() 为参数的 context 是作为最上层的父 context所有以其他 context 为参数的 context 都是他的子 context只要父 context 调用了 cancel() 则其所有的子 context 都会停止*/ctxParent, _ : context.WithTimeout(context.Background(), 6*time.Second)ctxChild, _ : context.WithCancel(ctxParent)wg.Add(1)go cpuIInfo(ctxChild)wg.Wait() }WithDeadline() 是指定某个时间点在某个时间点的时候进行执行 WithValue() 则会向 context 中传递一个数据我们可以在子 goroutine 中调用这个数据 var wg sync.WaitGroupfunc cpuIInfo(ctx context.Context) {defer wg.Done()for {select {case -ctx.Done(): // 本质还是一个 channelfmt.Println(程序退出执行...........)returndefault:time.Sleep(1 * time.Second)fmt.Printf(%s, ctx.Value(LeaderID))fmt.Println(CPUUUUUUUUUUUUUU)}} }func main() {/**这里有一个问题我们可以将以 context.Background() 为参数的 context 是作为最上层的父 context所有以其他 context 为参数的 context 都是他的子 context只要父 context 调用了 cancel() 则其所有的子 context 都会停止*/ctxParent, _ : context.WithTimeout(context.Background(), 6*time.Second)ctxChild : context.WithValue(ctxParent, LeaderID, 00001) // 注意 WithValue 方法只有一个返回值wg.Add(1)go cpuIInfo(ctxChild)wg.Wait() }
http://www.zqtcl.cn/news/903418/

相关文章:

  • 网站开发培训中心 市桥移动端ui
  • 高碑店地区网站建设上海排名十大装潢公司
  • 无锡自助建站网站还是新能源专业好
  • pc 手机网站 微站如何建设与维护网站
  • 大学生兼职网站开发毕设论文杭州网络排名优化
  • 做教育机器网站网站建设的步骤图
  • 桔子建站是什么平台郑州公司注册网上核名
  • 网站开发技能有哪些网站建设艾金手指科杰
  • 网站建设挂什么费用网站建设学那些课
  • 网站定位与功能分析在互联网公司做网站
  • 安阳网站建设兼职做网站推广有哪些公司
  • 网站制作的一般过程怎么用手机搭建网站
  • 备案 网站名称 怎么改深圳建网站公司
  • html 企业网站模板网站策划书免费
  • 网站建设销售ppt拖拽建站系统源码
  • 网站托管费用多少网站的开发流程
  • 周到的商城网站建设北京品牌网站
  • 网站开发费用属于什么科目网站建设考试多选题
  • c asp做网站wordpress4.5.2文章采集
  • 百度网站建设电话建立网站站建设可以吗
  • 网站后台代码在哪修改网站如何做下一页
  • 网站开发职业要求百度推广代理商与总公司的区别
  • 西安网站建设中心网页 网 址网站区别
  • 技术支持东莞网站建设机械seo岗位是什么意思
  • 做商城网站需要备案什么域名硬件开发工具有哪些
  • 网络网站制作技巧wordpress全文
  • 韩国原生ip站群服务器左右悬停代码网站
  • 专门做广东11选5的网站网站 备案 营业执照
  • 免费扑克网站wordpress弹出服务协议窗口
  • 网站的反爬一般怎样做网站右键屏蔽